AdvancedVPNDeployment.psm1

<#
    Set-VpnConnectionUsernamePassword - Owned by Paul Stancer.
    Huge thanks to Jeff Winn for the DotRas project (https://dotras.codeplex.com/)
    These two have been a great resource for this Module. I am using Paul's Module as a pre-requisite for my module
    since it is his and Jeff's work that made it possible to pass credentials to a vpn client
#>


clear
$Host.PrivateData.ProgressBackgroundColor='Black' 
$Host.PrivateData.ProgressForegroundColor='Cyan'




Function CreateVPNConnectionSyntax{

    $fclr1 = @{
        ForegroundColor = 'Green'
    }
    $fclr2 = @{
        ForegroundColor = 'White'
    }
    $fclr3 = @{
        ForegroundColor = 'DarkGray'
    }
    $fclr4 = @{
        ForegroundColor = 'red'
    }
    $nnl =@{
        NoNewline = $True
    }
    $tab = @{
        Object = "`t`t "
    }



    $Syntax = @(clear
    Write-Host "`n`n`n`n";
    Write-Host "Syntax: The below syntax is structured vertically, purely for a cleaner look.";
    Write-Host "`n`n";
    
    Write-Host "Create-MerakiVPNConnection " @fclr1 @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-ConnectionName "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3; 
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-ServerAddress "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3; 
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-SecretKey "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "] "@fclr3; 
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-Username "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3; 
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-Passwrd "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3; 
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-Domain "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3; 
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-AllUserConnection "@fclr1 @nnl; Write-Host "]"@fclr3;
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-RememberCredentials "@fclr1 @nnl; Write-Host "]"@fclr3;
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-TunnelType "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3;
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-AuthMethod "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3;
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-EncryptionLvl "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3;
    Write-Host @tab @nnl; Write-Host "["@fclr4 @nnl;Write-Host "["@fclr3 @nnl;Write-Host "-SplitTunneling"@fclr1 @nnl; Write-Host "] "@fclr3 @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-TunnelSubnet "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3 @nnl; Write-Host "] "@fclr4 @nnl; 
    Write-Host " " @nnl; Write-Host "<--- " @fclr3 @nnl; Write-Host "[" @fclr4 @nnl; Write-Host "Red brackets" @fclr3 @nnl; Write-Host "]" @fclr4 @nnl; Write-Host " means both parameters must be used together." @fclr3;
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-SecondsInIdleBeforeDisconnect "@fclr1 @nnl; Write-Host  "<int>"@fclr2 @nnl; Write-Host "]"@fclr3; 
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-DNS1 "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3; 
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-DNS2 "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3; 
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-DNSSuffix "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3;
    Write-Host @tab @nnl; Write-Host "["@fclr4 @nnl;Write-Host "["@fclr3 @nnl;Write-Host "-MakeHidden"@fclr1 @nnl; Write-Host "] "@fclr3 @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-HiddenPath"@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3 @nnl; Write-Host "] "@fclr4 @nnl; 
    Write-Host "`t " @nnl; Write-Host "<--- " @fclr3 @nnl; Write-Host "[" @fclr4 @nnl; Write-Host "Red brackets" @fclr3 @nnl; Write-Host "]" @fclr4 @nnl; Write-Host " means both parameters must be used together. [-HiddenPath] will not show without [-MakeHidden]" @fclr3;
    Write-Host @tab @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-SupressMessages "@fclr1 @nnl; Write-Host "]"@fclr3;
    
    
    
    Write-Host "`n`n`n`n";
    Write-Host "Example: The below example is structured vertically, purely for a cleaner look."
    Write-Host "`n`n";
    
    
    
    Write-Host "Create-MerakiVPNConnection -ConnectionName "@fclr1 @nnl; Write-Host """Company VPN"""@fclr2; 
    Write-Host @tab @nnl; Write-Host "-ServerAddress " @fclr1 @nnl; Write-host """somedummyaddress.ddns.com""" @fclr2; 
    Write-Host @tab @nnl; Write-Host "-SecretKey " @fclr1 @nnl; Write-Host """somesecretkeythisis""" @fclr2; 
    Write-Host @tab @nnl; Write-Host "-Username " @fclr1 @nnl; Write-Host """BobSmith""" @fclr2;
    Write-Host @tab @nnl; Write-Host "-Passwrd " @fclr1 @nnl; Write-host """PlainTextPwd1""" @nnl @fclr2; Write-Host "`t`t`t`t`t<--- Passwrd can be left empty with '' or $('$'+'Null') to specify masked password prompt" @fclr3;
    Write-Host @tab @nnl; Write-Host "-Domain " @fclr1 @nnl; Write-Host """Company.local""" @fclr2;
    Write-Host @tab @nnl; Write-Host "-AllUserConnection" @fclr1;
    Write-Host @tab @nnl; Write-Host "-RememberCredentials" @fclr1;
    Write-Host @tab @nnl; Write-Host "-TunnelType " @fclr1 @nnl; Write-Host """L2TP""" @fclr2;
    Write-Host @tab @nnl; Write-Host "-AuthMethod " @fclr1 @nnl; Write-Host """PAP""" @fclr2;
    Write-Host @tab @nnl; Write-Host "-EncryptionLvl " @fclr1 @nnl; Write-Host """Required""" @fclr2;
    Write-Host @tab @nnl; Write-Host "-SplitTunneling " @fclr1 @nnl; Write-Host " -TunnelSubnet " @fclr1 @nnl; Write-Host """0.0.0.0/24""" @fclr2;
    Write-Host @tab @nnl; Write-Host "-SecondsInIdleBeforeDisconnect " @fclr1 @nnl; Write-Host "0" @fclr2;
    Write-Host @tab @nnl; Write-Host "-DNS1 " @fclr1 @nnl; Write-Host """122.16.0.120""" @fclr2;
    Write-Host @tab @nnl; Write-Host "-DNSSuffix " @fclr1 @nnl; Write-Host """Company.Local""" @fclr2;
    Write-Host @tab @nnl; Write-Host "-MakeHidden " @fclr1 @nnl; Write-Host " -HiddenPath " @fclr1 @nnl; Write-Host """C:\Windows\HiddenPath\HiddenVPN.pbk""" @fclr2;
    
    Write-Host "`n`n`n";
    
    Write-Host "Notes:`n`n`n";
    
    Write-Host "1. " @fclr2 @nnl; Write-Host "[" @fclr3 @nnl; Write-Host "-Splittunneling" @fclr1 @nnl; Write-Host "] works differently than it does in [" @fclr3 @nnl; Write-Host "Add-VPNConnection" @fclr1 @nnl; Write-Host "] , as there is now the ability to add a subnet, which is mandatory if [" @fclr3 @nnl; Write-Host "-Splittunneling" @fclr1 @nnl; Write-Host "] is added.`n" @fclr3;
    
    Write-Host "2. " @fclr2 @nnl; Write-Host "Encryption Level is not specified as an option because [" @fclr3 @nnl; Write-Host "Add-VPNConnection" @fclr1 @nnl; Write-Host "] does not allow [" @fclr3 @nnl; Write-Host "Required" @fclr2 @nnl; Write-Host "] encryption with [" @fclr3 @nnl; Write-Host "PAP" @fclr2 @nnl; Write-Host "]. As a result, the encryption level is set to `n [" @fclr3 @nnl; Write-Host "Optional" @fclr2 @nnl; Write-Host "], and after the VPN is created, the module will modify the encrytion value to be [" @fclr3 @nnl; Write-Host "Required" @fclr2 @nnl; Write-Host "].`n" @fclr3;
    
    Write-Host "3. " @fclr2 @nnl; Write-Host "This module has the ability to be created under the system account. Doing so will allow the (" @fclr3 @nnl; Write-Host "Admin" @fclr2 @nnl; Write-Host ") the ability to create a scheduled script and task with the included `n command in the script: `n" @fclr3; Write-Host "`trasphone -f " @fclr1 @nnl; Write-Host """C:\FullPath\ToPBKfile\rasphone.pbk""" @fclr2 @nnl; Write-Host " -d " @fclr1 @nnl; Write-Host """Name of VPN Connection""`n`n" @fclr2;
    
    Write-Host "4. " @fclr2 @nnl; Write-Host "It is recommended to use atleast one [" @fclr3 @nnl; Write-Host "internal DNS" @fclr2 @nnl; Write-Host "] with the connection [" @fclr3 @nnl; Write-Host "-DNS1" @fclr1 @nnl; Write-Host "] to ensure the ability to reach internal workplace resources, preferrably the DNS server`n if domain or workplace resource machine if workgroup.`n" @fclr3;
    
    Write-Host "5. " @fclr2 @nnl; Write-Host "[" @fclr3 @nnl; Write-Host "-Username" @fclr1 @nnl; Write-Host "] and [" @fclr3 @nnl; Write-Host "-Passwrd" @fclr1 @nnl; Write-Host "] used are for the (" @fclr3 @nnl; Write-Host "Current User" @fclr2 @nnl; Write-Host ") profile. Meaning, Creating the connection at (" @fclr3 @nnl; Write-Host "SYSTEM" @fclr2 @nnl; Write-Host ") level means that the credentials used, will be stored`n for only the system account. If [" @fclr3 @nnl; Write-Host "-AllUserConnection" @fclr1 @nnl; Write-Host "] is specified, other users will have to add their own credentials or `n [" @fclr3 @nnl; Write-Host "Set-VpnConnectionUsernamePassword" @fclr1 @nnl; Write-Host "] [" @fclr3 @nnl; Write-Host "-username" @fclr1 @nnl; Write-Host "] [" @fclr3 @nnl; Write-Host "-password" @fclr1 @nnl; Write-Host "] [" @fclr3 @nnl; Write-Host "-domain" @fclr1 @nnl; Write-Host "] can be specified for each user as this module imports that module as well.`n" @fclr3;
    
    Write-Host "6. " @fclr2 @nnl; Write-Host "[" @fclr3 @nnl; Write-Host "-MakeHidden" @fclr1 @nnl; Write-Host "] and [" @fclr3 @nnl; Write-Host "-HiddenPath" @fclr1 @nnl; Write-Host "] are able to be used together. The " @fclr3 @nnl; Write-Host "[" @fclr3 @nnl; Write-Host "-HiddenPath" @fclr1 @nnl; Write-Host "] " @fclr3 @nnl; Write-Host "will allow you to choose where you want to save the hidden VPN. This will make the vpn`n not show in any lists and must be specified within the rasdial and/ or rasphone commands. (Check note 3 above for given example).`n" @fclr3;
    
    Write-Host "7. " @fclr2 @nnl; Write-Host "If a [ " @nnl @fclr3; Write-Host "-TunnelSubnet" @nnl @fclr1; Write-Host " ] is specified, moving the vpn to another location causes the dynamic route made with [ " @nnl @fclr3; Write-Host "Add-VpnConnectionRoute" @nnl @fclr2; Write-Host " ] to not work as this cmdlet looks`n for the .pbk file in the original pbk file homes. If the hidden vpn stays in these locations it will show up in the vpn list for others to use with their credentials.`n To ensure that moving the vpn works and the route is added if specified, the [ " @nnl @fclr3; Write-Host "Connect-VPNConnection" @nnl @fclr2; Write-Host " ] function is designed with checks in place to ensure that if a`n tunnel route is specified and doesnt exist already for the connection, that it gets added when the VPN connects.`n" @fclr3;

    Write-Host "8. " @fclr2 @nnl; Write-Host "[ " @nnl @fclr3; Write-Host "-SupressMessages" @nnl @fclr1; Write-Host " ] can be used to supress all informational messages. Warnings and errors will still be delivered to the console. Please note that this will supress`n comments regarding hidden VPN information if [ " @nnl @fclr3; Write-Host "-MakeHidden" @nnl @fclr1; Write-Host " ] is used, and should only be specified if it is not, or if ran in a script.`n`n" @fclr3;

    Write-Host "`tCheck:" @nnl @fclr3; Write-Host "`tConnect-VPNConnection -Syntax " @nnl @fclr1; Write-Host "`t for information on how to use the connection function`n`n" @fclr3;

    )


return $Syntax

break;
}






Function ConnectVPNConnectionSyntax {



    $fclr1 = @{
        ForegroundColor = 'Green'
    }
    $fclr2 = @{
        ForegroundColor = 'White'
    }
    $fclr3 = @{
        ForegroundColor = 'DarkGray'
    }
    $fclr4 = @{
        ForegroundColor = 'red'
    }
    $nnl =@{
        NoNewline = $True
    }
    $tab = @{
        Object = "`t`t "
    }






$Syntax = @(Clear


Write-Host "`n`n`n`n";
Write-Host "Syntax: The below syntax is structured vertically, purely for a cleaner look.";
Write-Host "`n`n";
Write-Host "Connect-VPNConnection "  @nnl @fclr1;Write-Host "[" @nnl @fclr3; Write-Host "-ConnectionName " @nnl @fclr1; Write-Host "<string>" @nnl @fclr2; Write-Host "]" @fclr3;
Write-Host @tab @nnl; Write-Host "[" @nnl @fclr3; Write-Host "-Username " @nnl @fclr1; Write-Host "<string>" @nnl @fclr2; Write-Host "]" @fclr3;
Write-Host @tab @nnl; Write-Host "[" @nnl @fclr3; Write-Host "-Passwrd " @nnl @fclr1; Write-Host "<string>" @nnl @fclr2; Write-Host "]" @fclr3;
Write-Host @tab @nnl; Write-Host "[" @nnl @fclr3; Write-Host "-Domain" @nnl @fclr1; Write-Host "<string>" @nnl @fclr2; Write-Host "]" @fclr3;
Write-Host @tab @nnl; Write-Host "["@fclr4 @nnl;Write-Host "["@fclr3 @nnl;Write-Host "-CustomPhoneBook"@fclr1 @nnl; Write-Host "] "@fclr3 @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-Path "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3 @nnl; Write-Host "] "@fclr4 @nnl; 
Write-Host " " @nnl; Write-Host "<--- " @fclr3 @nnl; Write-Host "[" @fclr4 @nnl; Write-Host "Red brackets" @fclr3 @nnl; Write-Host "]" @fclr4 @nnl; Write-Host " means both parameters must be used together.`n`n" @fclr3;



Write-Host "Connect-VPNConnection "  @nnl @fclr1; Write-Host "[" @nnl @fclr3; Write-Host "-ConnectionName " @nnl @fclr1; Write-Host "<string>" @nnl @fclr2; Write-Host "]" @fclr3;
Write-Host @tab @nnl; Write-Host "[" @nnl @fclr3; Write-Host "-UseCachedCredentials " @nnl @fclr1; Write-Host "]" @fclr3;
Write-Host @tab @nnl; Write-Host "["@fclr4 @nnl;Write-Host "["@fclr3 @nnl;Write-Host "-CustomPhoneBook"@fclr1 @nnl; Write-Host "] "@fclr3 @nnl; Write-Host "["@fclr3 @nnl;Write-Host "-Path "@fclr1 @nnl; Write-Host  "<string>"@fclr2 @nnl; Write-Host "]"@fclr3 @nnl; Write-Host "] "@fclr4 @nnl; 
Write-Host " " @nnl; Write-Host "<--- " @fclr3 @nnl; Write-Host "[" @fclr4 @nnl; Write-Host "Red brackets" @fclr3 @nnl; Write-Host "]" @fclr4 @nnl; Write-Host " means both parameters must be used together.`n" @fclr3;

Write-Host "`n`n`n`n";
Write-Host "Example: The below example is structured vertically, purely for a cleaner look."
Write-Host "`n`n";

Write-Host "Connect-VPNConnection "  @nnl @fclr1; Write-Host "-ConnectionName " @nnl @fclr1; Write-Host """Company VPN""" @fclr2;
Write-Host @tab @nnl; Write-Host "-Username " @nnl @fclr1; Write-Host """BobSmith""" @fclr2;
Write-Host @tab @nnl; Write-Host "-Passwrd " @nnl @fclr1; Write-Host """SomePlainTextPassword""" @fclr2;
Write-Host @tab @nnl; Write-Host "-Domain" @nnl @fclr1; Write-Host """Company""" @fclr2;
Write-Host @tab @nnl; Write-Host "-CustomPhoneBook -Path " @nnl @fclr1; Write-Host """C:\CustomPathTo\PbkFile.pbk""" @nnl @fclr2; Write-Host "`n`n" @fclr3;

Write-Host "Connect-VPNConnection "  @nnl @fclr1; Write-Host "-ConnectionName " @nnl @fclr1; Write-Host """Company VPN""" @fclr2;
Write-Host @tab @nnl; Write-Host "-UseCachedCredentials "@fclr1;
Write-Host @tab @nnl; Write-Host "-CustomPhoneBook -Path " @nnl @fclr1; Write-Host """C:\CustomPathTo\PbkFile.pbk""" @nnl @fclr2; Write-Host "`n`n`n" @fclr3;

Write-Host "`n`nNotes:`n`n" @fclr2;
Write-Host "1. " @nnl @fclr2; Write-Host "Do to a bug in [ " @nnl @fclr3; Write-Host " Add-VPNConnectionRoute " @nnl @fclr1; Write-Host " ], if a tunnelroute was added for splittunneling, when connecting to the route`n under the SYSTEM account, the route will not attach dynamically. Instead, a check is in place to add the route if connected`n under system account, using an alternate method.`n" @fclr3;
Write-Host "2. " @nnl @fclr2; Write-Host "[ " @nnl @fclr3; Write-Host " Disconnect-VPNConnection -ConnectionName " @nnl @fclr1; Write-Host """Name of VPN""" @nnl @fclr2; Write-Host " ] can be used to disconnect VPN`n`n`n" @fclr3;





)




return $Syntax

break;


}












Function Create-AdvancedVPNConnection{

    
    [CmdletBinding(DefaultParameterSetName='Connect')]
    param (
        
    
        [Parameter(Mandatory=$True, Position=0, ParameterSetName='Connect')]
        [String]$ConnectionName,

        [Parameter(Mandatory=$True, Position=1, ParameterSetName='Connect')]
        [String]$ServerAddress,

        [Parameter(Mandatory=$True, Position=2, ParameterSetName='Connect')]
        [String]$SecretKey,

        [Parameter(Mandatory=$False, Position=3, ParameterSetName='Connect')]
        [AllowNull()]
        [String]$Username,

        [Parameter(Mandatory=$False, Position=4, ParameterSetName='Connect')]
        [AllowNull()]
        [String]$Passwrd,
        
        [Parameter(Mandatory=$False, Position=5, ParameterSetName='Connect')]
        [AllowNull()]
        [String]$Domain,

        [Parameter(Mandatory=$False, Position=6, ParameterSetName='Connect')]
        [Switch]$AllUserConnection,

        [Parameter(Mandatory=$False, Position=7, ParameterSetName='Connect')]
        [Switch]$RememberCredentials,

        [Parameter(Mandatory=$False, Position=8, ParameterSetName='Connect')]
        [ValidateSet('None','Optional','Required','Maximum')]
        [String]$EncryptionLvl,

        [Parameter(Mandatory=$False, Position=9, ParameterSetName='Connect')]
        [ValidateSet('AUTO','PPTP','L2TP','SSTP','IKEv2')]
        [String]$TunnelType,

        [Parameter(Mandatory=$False, Position=10, ParameterSetName='Connect')]
        [ValidateSet('CHAP','MSCHAPv2','PAP')]
        [String]$AuthMethod,

        [Parameter(Mandatory=$False, Position=11, ParameterSetName='Connect')]
        [Switch]$SplitTunneling,

        [Parameter(Mandatory=$False, Position=12, ParameterSetName='Connect')]
        [Int]$SecondsInIdleBeforeDisconnect,

        [Parameter(Mandatory=$False, Position=13, ParameterSetName='Connect')]
        [String]$DNS1='0.0.0.0',

        [Parameter(Mandatory=$False, Position=14, ParameterSetName='Connect')]
        [String]$DNS2='0.0.0.0',

        [Parameter(Mandatory=$False, Position=15, ParameterSetName='Connect')]
        [String]$DNSSuffix,

        [Parameter(Mandatory=$False, Position=16, ParameterSetName='Connect')]
        [Switch]$MakeHidden,

        [Parameter(Mandatory=$False, Position=17, ParameterSetName='Connect')]
        [Switch]$SupressMessages,

        [Parameter(Mandatory=$False, Position=1, ParameterSetName='Syntax')]
        [Switch]$Syntax,

        [parameter(DontShow)]
        $VerbosePreference,
        [parameter(DontShow)]
        $WarningPreference,
        [parameter(DontShow)]
        $ConfirmPreference,
        [parameter(DontShow)]
        $DebugPreference

        

    )

    DynamicParam{

            $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary


            If($SplitTunneling)
            {

            $paramTemplate = 'TunnelSubnet'
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
            $ParameterAttribute.Mandatory = $True
            $ParameterAttribute.ParameterSetName = 'Connect'
            $ParameterAttribute.HelpMessage = 'You must enter the subnet as (Ex. 192.168.11.0/24)'
            $AttributeCollection.Add($ParameterAttribute)
            
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($paramTemplate, [System.Object],$AttributeCollection)
            $RuntimeParameterDictionary.Add($paramTemplate, $RuntimeParameter) 
        

            }
        
       
            If($MakeHidden)
            {
            $paramTemplate = 'HiddenPath'
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
            $ParameterAttribute.Mandatory = $True
            $ParameterAttribute.ParameterSetName = 'Connect'
            $ParameterAttribute.HelpMessage = 'You must enter a path for the hidden phonebook to exist'
            $AttributeCollection.Add($ParameterAttribute)
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($paramTemplate, [System.Object],$AttributeCollection)
            $RuntimeParameterDictionary.Add($paramTemplate, $RuntimeParameter) 
                
            }



            return $RuntimeParameterDictionary
            
        


            







    }

Begin{

    
    $TunnelSubnet = $PSBoundParameters.TunnelSubnet
    $HiddenPath = $PSBoundParameters.HiddenPath
    

}



Process{


    If('VPNCredentialsHelper' -notin (Get-InstalledModule).Name){
        Install-Module -Name VPNCredentialsHelper -Force -Scope AllUsers | Import-Module -force -Global
    }
    








    $fclr1 = @{
        ForegroundColor = 'Green'
    }
    $fclr2 = @{
        ForegroundColor = 'White'
    }
    $fclr3 = @{
        ForegroundColor = 'DarkGray'
    }
    $fclr4 = @{
        ForegroundColor = 'red'
    }
    $fclr5 = @{
        ForegroundColor = 'cyan'
    }
    $nnl =@{
        NoNewline = $True
    }
    $tab = @{
        Object = "`t`t "
    }
      
    




Function HiddenPathNotes{

$Notes = $(

Write-Host "INFORMATION: " @fclr5; Write-Host "Your HiddenVPN can now be found at [ " @nnl @fclr3; Write-Host "$HiddenPath" @nnl @fclr2; Write-Host " ] and will not`nshow up in any vpn list. You can use any of the following to connect:`n" @fclr3;

Write-Host "rasphone -f " @nnl @fclr1; Write-Host ""$HiddenPath"" @nnl @fclr2; Write-Host " -d" @nnl @fclr1; Write-Host ""$ConnectionName`n"" @fclr2;

Write-Host "rasdial " @nnl @fclr1; Write-Host ""$ConnectionName"" ""username"" ""password""  /Domain:"" @nnl @fclr2; Write-Host ""YourDomain" " @nnl @fclr3; Write-Host  "/PHONEBOOK:" @nnl @fclr2; Write-Host ""$HiddenPath"`n" @fclr3; 

Write-Host "Recommended: " @nnl @fclr4; Write-Host "[ " @nnl @fclr3; Write-Host "Connect-VPNConnection" @nnl @fclr1; Write-Host " ], See below notes.`n`n`n" @nnl @fclr3;


Write-Host "Notes:`n`n"

Write-Host "1. " @nnl @fclr2; Write-Host  "Domain is optional, but recommended if account belongs to domain with VPN-AD Integration.`n" @fclr3;

Write-Host "2. " @nnl @fclr2; Write-Host "[" @nnl @fclr3; Write-Host "Connect-VPNConnection -Syntax" @nnl @fclr1; Write-Host "] and learn how to use the new connection function for the vpn connection`n" @fclr3;


)


return $Notes

}








Switch($Syntax){



'False'{

           


            If($SplitTunneling)
            {

                    If($TunnelSubnet -notmatch '\d+.+\/\d{2}\b')
                    {
                    Write-Warning 'You must enter the subnet as (Ex. 192.168.0.0/24 or 77.55.0.0/32 or similar)'
                    break;
                    }

            }


           

            If($MakeHidden -and $HiddenPath -notmatch '.pbk$'){
                
                Write-Warning 'You must specify the full path, including the name of the phonebook file with the ending [.pbk] extension. <--> (Ex. ''C:\Windows\HiddenFolder\HiddenVPN.pbk'')'
                break;
            }
            



    Switch -regex ($EncryptionLvl){


        'None'{
            [int]$EncryptionLvl = 0
        }
        'Optional'{
            [int]$EncryptionLvl = 8
        }
        'Required'{
            [int]$EncryptionLvl = 256
        }
        'Maximum'{
            [int]$EncryptionLvl = 512
        }


    }








    Clear
    $Host.PrivateData.ProgressBackgroundColor='Black'
    $Host.PrivateData.ProgressForegroundColor='Cyan'


$VPNConnectionSettings = @{
    Name = "$ConnectionName" 
    ServerAddress = "$($ServerAddress)" 
    TunnelType = "$($TunnelType)" 
    L2tpPsk = "$($SecretKey)"
    AuthenticationMethod = "$($AuthMethod)" 
    AllUserConnection = $($AllUserConnection)
    RememberCredential = $($RememberCredentials)
    DnsSuffix = "$($DNSSuffix)"
    Force = $True 
    EncryptionLevel = 'Optional'
    IdleDisconnectSeconds = $($SecondsInIdleBeforeDisconnect) 
    WarningAction = 'SilentlyContinue'
    
}


Try{

Add-VpnConnection @VPNConnectionSettings | Out-Null


            If("$ConnectionName" -in (Get-VpnConnection).Name -or (Get-VpnConnection -AllUserConnection).Name)
            {

            If(!$SupressMessages){

            Write-Host "INFORMATION: " @fclr5; Write-Host "[" @nnl @fclr3; Write-Host "$ConnectionName" @nnl @fclr2; Write-Host "] created in network list on [" @nnl @fclr3; Write-Host "$([Environment]::MACHINENAME)" @nnl @fclr2; Write-Host " ] for [ " @nnl @fclr3; Write-Host "$([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)" @nnl @fclr2; Write-Host " ] `n`n" @fclr3;
            }
            }
            Else{
                return Write-Warning "Not finding [$ConnectionName] in network list. Please try command again.`n`n"
                break;
                }



}
Catch{

    Write-Warning "$($_.Exception.Message)"
    break;
}








            If(![String]::IsNullOrEmpty($Username) -and [String]::IsNullOrEmpty($Passwrd))
                {
                    While($($SecurePasswrd.Length -le 0)){
                    clear
                    $SecurePasswrd = Read-Host -Prompt "`nEnter Secure Password" -AsSecureString
                    }

                    $Passwrd = (New-Object PSCredential "$Username",$SecurePasswrd).GetNetworkCredential().Password

                }Else
                    {
                        $Passwrd = $Passwrd
                    }






            If(![string]::IsNullOrEmpty($Username) -and ![string]::IsNullOrEmpty($Passwrd))
            {

                $VPNConnectionCreds = @{
                    connectionname = "$($ConnectionName)"
                    domain = "$($Domain)"
                    username = "$($Username)"
                    password = "$($Passwrd)"
                }
                
                
                Try{


                Set-VpnConnectionUsernamePassword @VPNConnectionCreds | Out-Null
                }

                Catch{

                    Write-Warning "$($_.Exception.Message)"
                    break;
                }
                
                
            }








If($SplitTunneling)
{
    
    $IPPrioritize = 'IpPrioritizeRemote=0' 
}
Else{

    $IPPrioritize = 'IpPrioritizeRemote=1'

    }







$Path = (GCI "$($Env:USERPROFILE)",'C:\Users\All Users' -filter '*.pbk' -recurse -force -ErrorAction SilentlyContinue | ?{
(Get-Content $_.FullName -raw) -match "(\[$($ConnectionName)\]((?:.*?\n)*?)TryNextAlternateOnFail=1)"}).FullName




$ModifiedValue = (((((((((((Get-Content "$Path" -Raw | Select-String -AllMatches -Pattern "(\[$($ConnectionName)\]((?:.*?\n)*?)TryNextAlternateOnFail=1)").Matches.Value`
-replace 'DataEncryption=\d+',"DataEncryption=$($EncryptionLvl)")`
-replace 'IdleDisconnectSeconds=0',"IdleDisconnectSeconds=$($SecondsInIdleBeforeDisconnect)")`
-replace 'IpDnsAddress=0.0.0.0',"IpDnsAddress=$($DNS1)")`
-replace 'IpDns2Address=0.0.0.0',"IpDns2Address=$($DNS2)")`
-replace 'IpPrioritizeRemote=\w+',"$($IPPrioritize)")`
-replace 'PreviewUserPw=\d','PreviewUserPw=0')`
-replace 'PreviewDomain=\d','PreviewDomain=0')`
-replace 'ShowDialingProgress=\d','ShowDialingProgress=0')`
-replace 'ShowMonitorIconInTaskBar=\d','ShowMonitorIconInTaskBar=0')`
-replace 'RedialSeconds=60','RedialSeconds=5')`
-replace 'Comment=',"Comment=$($TunnelSubnet)"




(Get-Content $Path -Raw) -replace "(\[$($ConnectionName)\]((?:.*?\n)*?)TryNextAlternateOnFail=1)","$($ModifiedValue)" | Out-File $Path -Force -Encoding ascii





                                If($SplitTunneling)
                                {
                                    
                                        $AVCR = @{

                                            ConnectionName = "$($ConnectionName)"
                                            DestinationPrefix = "$($TunnelSubnet)"
                                            AllUserConnection = $($AllUserConnection)
                                            Confirm = $False
                                                }

                                        
                                            Add-VpnConnectionRoute @AVCR
                                        
                                                If(!$SupressMessages)
                                                {
                                                    Write-Host "INFORMATION: " @fclr5; Write-Host "The [ " @nnl @fclr3; Write-Host "$TunnelSubnet" @nnl @fclr2; Write-Host " ] route had been added to [ " @nnl @fclr3; Write-Host "$ConnectionName" @nnl @fclr2; Write-Host "] `n`n" @fclr3;
                                                }
                                }


        If($MakeHidden)
        {


            $SourcePath = (Get-Content "$Path" -Raw | Select-String -AllMatches -Pattern "(\[$ConnectionName\]((?:.*?\n)*?)TryNextAlternateOnFail=1)").Matches.Value

            $SourcePath | Out-File (New-Item "$HiddenPath" -ItemType File -Force) -Encoding ascii

            (Get-Content $Path -Raw) -replace "(\[$ConnectionName\]((?:.*?\n)*?)TryNextAlternateOnFail=1)",'' | Out-File $Path -Force -Encoding ascii


                    If(Test-Path "$HiddenPath")
                    {
                    
                        If(!$SupressMessages){
                        HiddenPathNotes
                        }

                    }



        } #<-- End 'MakeHidden' If/Switch


    } #<--- End 'False' for Syntax Switch



'True'{



    CreateVPNConnectionSyntax        #<--- Calls Syntax layout for Creating VPN Connection
        

} #<--- End 'True' for 'Syntax' Switch



} #<--- End 'Syntax' Switch




} #<--- End 'Process'





} #<--- End 'Create-MerakiVPnConnection'












Function Connect-VPNConnection{



    [CmdletBinding(DefaultParameterSetName='Connect')]
    param (
        
        [Parameter(Mandatory=$True, Position=0, ParameterSetName='Connect')]
        [Parameter(Mandatory=$True, Position=0, ParameterSetName='UseCachedCredentials')]
        [String]$ConnectionName,
        
        [Parameter(Mandatory=$True, Position=0, ParameterSetName='Connect')]
        [String]$Username,
        
        [Parameter(Mandatory=$False, Position=0, ParameterSetName='Connect')]
        [AllowEmptyString()]
        [AllowNull()]
        [String]$Passwrd,
        
        [Parameter(Mandatory=$False, Position=0, ParameterSetName='Connect')]
        [AllowEmptyString()]
        [AllowNull()]
        [String]$Domain,
        
        [Parameter(Mandatory=$True, Position=1, ParameterSetName='UseCachedCredentials')]
        [Switch]$UseCachedCredentials,

        [Parameter(Mandatory=$False, Position=1, ParameterSetName='Connect')]
        [Parameter(Mandatory=$False, Position=0, ParameterSetName='UseCachedCredentials')]
        [Switch]$CustomPhoneBook,

        [Parameter(Mandatory=$False, Position=1, ParameterSetName='Syntax')]
        [Switch]$Syntax,

       

        [parameter(DontShow)]
        $VerbosePreference,
        [parameter(DontShow)]
        $WarningPreference,
        [parameter(DontShow)]
        $ConfirmPreference,
        [parameter(DontShow)]
        $DebugPreference

       

    )



    DynamicParam{


        $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary


        
        
        If($CustomPhoneBook){
        
        $paramTemplate = 'Path'
        $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
        $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
        $ParameterAttribute.Mandatory = $True
        $ParameterAttribute.Position = 4
        $ParameterAttribute.HelpMessage = 'You must enter a path for the hidden phonebook to exist'
        $AttributeCollection.Add($ParameterAttribute)
        
        $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($paramTemplate, [System.String],$AttributeCollection)
        $RuntimeParameterDictionary.Add($paramTemplate, $RuntimeParameter) 

        }
                
            


            return $RuntimeParameterDictionary



    }




Begin{

        $Path = $PSBoundParameters.Path
        $Username = $PSBoundParameters.Username
        $Passwrd = $PSBoundParameters.Passwrd
        $Domain = $PSBoundParameters.Domain

}






Process{


    $fclr1 = @{
        ForegroundColor = 'Green'
    }
    $fclr2 = @{
        ForegroundColor = 'White'
    }
    $fclr3 = @{
        ForegroundColor = 'DarkGray'
    }
    $fclr4 = @{
        ForegroundColor = 'red'
    }
    $fclr5 = @{
        ForegroundColor = 'cyan'
    }
    $nnl =@{
        NoNewline = $True
    }
    $tab = @{
        Object = "`t`t "
    }


Function rasdialStatus{
       
    
   
   

    If((($rasdialStatus | Select-String '(Remote Access error.+.)|(Successfully.+.)' -AllMatches).Matches.Value) -match '(Remote Access error.+.)')
    {
        Clear
        Write-Host "`nERROR:" @fclr4; Write-Host "Connection to the server failed. Either connection is internal, the credentials used are invalid`nor something is preventing the connection to the destination network. " @fclr3; Write-Host "Terminating Program. `n" @fclr4;
        break rasdialStatus
    }
    ElseIf((($rasdialStatus | Select-String '(Remote Access error.+.)|(Successfully.+.)' -AllMatches).Matches.Value) -match '(Successfully.+.)')
    {
        
        Clear
        return $(Write-Host "`n$ConnectionName " @nnl @fclr3; Write-Host " <--> " @nnl @fclr2; Write-Host " Connected `n" @fclr1;)
        
    }

    

}









Function rasphonemonitor{

    $Date = (Get-Date).AddSeconds(20)

    $ErrorActionPreference = 'SilentlyContinue'
    clear
Write-Progress -ID 0 -Activity 'Dialing in...' -Status ' '

    While([bool](Get-Process | ?{$_.Name -match 'rasphone'}))
    {

                If([bool](Get-Process | ?{$_.Name -match 'rasphone'}) -and (Get-Date) -gt $Date)
                {
                    
                    $RasID = (Get-Process 'rasphone').ID
                    Stop-Process -Id $RasID -force
                    
                    Write-Host "`nERROR:" @fclr4; Write-Host "Connection to the server failed. Either connection is internal or something is preventing`nthe connection to the destination network. " @fclr3; Write-Host "Terminating Program. `n" @fclr4;
                    
                    break rasphonemonitor
                }
               

    }        
    
      
Write-Progress -ID 0 -Activity ' '  -Completed

}







Function rasphoneDialStatus{


    
    $ErrorActionPreference = 'SilentlyContinue'
    
    $Time = [datetime]::Now.AddSeconds(30)
    While($True){
    
    
    If((Get-WinEvent -LogName 'Application'-MaxEvents 3).Count -gt 0 -and 'RasClient' -in (Get-WinEvent -LogName 'Application'-MaxEvents 3).ProviderName -and (Get-WinEvent -LogName 'Application' -MaxEvents 3).Message -match "($ConnectionName.+successfully connected\b)")
    {
        
        return $(Write-Host "`n`n$ConnectionName " -NoNewline -ForegroundColor 'DarkGray'; Write-Host " <--> " -NoNewline -ForegroundColor 'White'; Write-Host " Connected`n`n" -ForegroundColor 'Green')
        break;
    }
    ElseIf((Get-WinEvent -LogName 'Application' -MaxEvents 3).Count -gt 0 -and 'RasClient' -in (Get-WinEvent -LogName 'Application' -MaxEvents 3).ProviderName -and (Get-WinEvent -LogName 'Application' -MaxEvents 3).Message -match "$ConnectionName.+fail")
    {
        
        return $(Write-Host "`n`n$ConnectionName " -NoNewline -ForegroundColor 'DarkGray'; Write-Host " <--> " -NoNewline -ForegroundColor 'White'; Write-Host " Failed Connection `n`n" -ForegroundColor 'Red')
        
        
        break;
    
    }
    If([datetime]::Now -gt $Time){
        Clear
        return Write-Warning " `n Something caused internal failure. Please check connection manually by sending ping response to network. Terminating `n"
        break;
    }
    
    
    
    
    Start-Sleep -Seconds 1
    
    }




}





    


        Switch($Syntax){


        'False'{

            Switch($CustomPhoneBook){

            'True' {
                
                    $BookPath = "$Path"
            }
            'False'{
              
                    [Array]$BookPath = @("$Env:ProgramData\Microsoft\Network\Connections\Pbk","$Env:USERPROFILE\AppData\Roaming\Microsoft\Network\Connections\Pbk")
                    
                }
            }
            

                If("$ConnectionName" -in (Get-NetIpAddress).InterfaceAlias){

                    return $(Write-Host "`n`n$ConnectionName " -NoNewline -ForegroundColor 'DarkGray'; Write-Host " <--> " -NoNewline -ForegroundColor 'White'; Write-Host " Already Connected`n`n" -ForegroundColor 'Green')
                    break;

                }


                $ErrorActionPreference = 'SilentlyContinue'
    
                
                $phoneBook = ($BookPath | GCI -Filter '*.pbk' -Force -Recurse | ?{ (Get-Content $_.FullName -raw) -match "(\[$ConnectionName\]((?:.*?\n)*?)TryNextAlternateOnFail=1)"}).FullName
                
                If([String]::IsNullOrEmpty($phoneBook)){
                    Write-Warning "$($ConnectionName) doesnt exist in this phonebook as an entry. Either check the spelling of the connection or check the entry in the phonebook file and try again."
                    break;
                }


    
            Switch($UseCachedCredentials){
    
                'True'{
    
                
                rasphone -f "$($phoneBook)" -d "$($ConnectionName)"
    
                rasphonemonitor
    
                rasphoneDialStatus
    
    
                }
                'False'{

                    
                        If([String]::IsNullOrEmpty($Passwrd))
                        {
                            While($($SecurePasswrd.Length -le 0)){
                            clear
                            $SecurePasswrd = Read-Host -Prompt "`nEnter Secure Password" -AsSecureString
                            }

                            $Passwrd = (New-Object PSCredential "$Username",$SecurePasswrd).GetNetworkCredential().Password

                        }

                        Clear
                        Write-Progress -ID 0 -Activity 'Dialing in...' -Status ' '

                        $rasdialStatus = rasdial "$ConnectionName" "$Username" "$Passwrd" /DOMAIN:"$($Domain)" /PHONEBOOK:"$($phoneBook)"

                        Write-Progress -ID 0 -Activity ' '  -Completed

                        rasdialStatus

                        
    
                }
    
    
    
    
    
                    } #<--- End of 'UseCachedCredentials' Switch

                    If([System.Security.Principal.WindowsIdentity]::GetCurrent().Name -match 'SYSTEM')
                    {
                            If(![String]::IsNullOrEmpty($phoneBook))
                            {

                            $TunnelSubnet = (((Get-Content "$phoneBook" -Raw | Select-String -AllMatches -Pattern "(\[$($ConnectionName)\]((?:.*?\n)*?)TryNextAlternateOnFail=1)").Matches.Value | 
                            Select-String -AllMatches -Pattern "Comment=.+").Matches |
                            Select-String -AllMatches -Pattern '(\d+.+\/\d{2}\b)').Matches.Value

                                    If(![String]::IsNullOrEmpty($TunnelSubnet))
                                    {

                                        While("$ConnectionName" -notin (Get-NetRoute -InterfaceAlias)){
                                            Start-Sleep -seconds 1
                                        }

                                        If("$TunnelSubnet" -notin (Get-NetRoute -InterfaceAlias "$ConnectionName").DestinationPrefix)
                                        {
                                            New-NetRoute -InterfaceAlias "$ConnectionName" -DestinationPrefix "$TunnelSubnet" -ErrorAction 'SilentlyContinue' | Out-Null
                                            Write-Host "INFORMATION:" @fclr5; Write-Host "$((Get-NetRoute -InterfaceAlias "$ConnectionName").DestinationPrefix -match "$TunnelSubnet")" @nnl @fclr1; Write-Host " has been added to a permanent route list`n`n`n" @fclr3;
                                        }
                                        
                                    }


                            }
                            
                    }

                    





        }  #<--- End of False 'Syntax' Switch
        'True'{

            ConnectVPNConnectionSyntax
            

        }
    }



       

    } #<--- End 'Process'






} #<--- End 'Connect-VPNConnection'








Function Disconnect-VPNConnection {



[CmdletBinding(DefaultParameterSetName='Connect')]
param (
    

    [Parameter(Mandatory=$True, Position=0, ParameterSetName='Connect')]
    [String]$ConnectionName,


    [parameter(DontShow)]
    $VerbosePreference,
    [parameter(DontShow)]
    $WarningPreference,
    [parameter(DontShow)]
    $ConfirmPreference,
    [parameter(DontShow)]
    $DebugPreference

    

)


$fclr1 = @{
    ForegroundColor = 'Green'
}
$fclr2 = @{
    ForegroundColor = 'White'
}
$fclr3 = @{
    ForegroundColor = 'DarkGray'
}
$fclr4 = @{
    ForegroundColor = 'red'
}
$nnl =@{
    NoNewline = $True
}
$tab = @{
    Object = "`t`t "
}






rasdial "$ConnectionName" /DISCONNECT | Out-Null


            

                $Count=0

                    While("$ConnectionName" -in (Get-NetIpAddress).InterfaceAlias)
                    {

                        Start-Sleep -Seconds 1

                            If("$ConnectionName" -in (Get-NetIpAddress).InterfaceAlias -and $Count -gt 5 )
                            {
                                
                                
                                return $(Write-Host "`nERROR:" @fclr4; Write-Host "Something is preventing ---| " @nnl @fclr3; Write-Host "$ConnectionName" @nnl @fclr2; Write-Host " |--- from disconnecting. Please try again. If issues persist, something may be preventing a disconnect and will likely need a system reboot.`n" @fclr3;)
                                
                                break rasDialDisconnect
                            }

                        $Count++

                    }


            
                Write-Host "`n`n$ConnectionName " @nnl @fclr3; Write-Host "<--> " @nnl @fclr2; Write-Host "Disconnected`n`n" @fclr4;




}


# SIG # Begin signature block
# MIIFZwYJKoZIhvcNAQcCoIIFWDCCBVQCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU0UkgWyhrrY3J0IthTpZACMLu
# BCygggMEMIIDADCCAeigAwIBAgIQYflG1yIAAbxJYYDpAW7BtzANBgkqhkiG9w0B
# AQUFADAYMRYwFAYDVQQDDA1Db2RlU2lnbmF0dXJlMB4XDTIwMTEwMjE5NTEwMVoX
# DTM1MTEwMjIwMDEwMlowGDEWMBQGA1UEAwwNQ29kZVNpZ25hdHVyZTCCASIwDQYJ
# KoZIhvcNAQEBBQADggEPADCCAQoCggEBALt/7ShMh3ybHqoiliRRV5RGxDpOTn0x
# 5sg0e3V1dCNj9FnJ9lWRYYMRZmq4ADcgJdgobOh4NZq50POXtJP9cKqv1TVQPS2o
# TnxYpO5MuEGi0Yd1I3y4jtZtDtBc07t4dUbQOWGYy2//ZhaBR6jcvAwz4vVWD7LF
# c6irhJ2dABscrtlFB5KoIbRbq2orrxh0FY6tVP2A9I1xn1JQvNiHwpevKZglNLBj
# mwTruqKWx2CK7KJacZeAtue7HYRzfeiv1qRi5y7n2h3d9ctjQkA/KRuj2xkWl9xs
# LV2lQoRn5kOmK6RDmw2+biRO84ISBmmb8ueK91f1queOwUZtIQrpnM0CAwEAAaNG
# MEQwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQW
# BBT3K9wScqB7lgdls9HAJm+ARMUxGTANBgkqhkiG9w0BAQUFAAOCAQEAcbwfWlMa
# G+ySVjv7AqBx9F5lWs8L84QrbN5pO5haRxNgageUJv6DJ6ezs1Z6YWxzGPfcktg8
# 0goJIcHgVJr1hD8J7DYa46zaswRPGyZzVpUquQRO4SIHGNftRqNXitpJPuWl20Gr
# ZslnQLNHpemoYgejka/B6QN5TKTY44kKAl16y3BPVJa+3XbCjt2hroyNqHshJaic
# qGtnl4pOd3J5QH3FHmy2XRZIcD+0RB42tvq9XQuuKBAmrWf8diPGgRyCFeAsD9nb
# YK5tshvYFRuTaijcrT/csiY8CNsc6yXuIe1GA1QYYuvsWTS0MoisYi1XmBugV1/P
# N3ec7J+IhkcMVjGCAc0wggHJAgEBMCwwGDEWMBQGA1UEAwwNQ29kZVNpZ25hdHVy
# ZQIQYflG1yIAAbxJYYDpAW7BtzAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEK
# MAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3
# AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUCQfaX8wgtJFhmL+o
# 9+2RsD/HFwowDQYJKoZIhvcNAQEBBQAEggEADm081eQLw3/3au8awYwq6TjPr6uR
# fsBhdLWkre0vSjmHMVi8VpzkXsosZxiBtzrOCxTWwsCc13N+gDRyINs7UfeCTD5A
# XCWR2wiJpADcYjYJCvqJREx0kR7Z9Bh46ShTjwzoH2zDXrmPaohSOM64N7RCn2RV
# 61YjVbmVZYWHfc0FPV5cnEdUc2giwSLcGuOIQQTp4tkrfWCgICmqVvORCEI3k7tA
# rv9JWUplcF3kVhH2MtvTbfdQ7kW3cfbDlzs6AekzJ/PKq90HCyuirvwypJnVnNDR
# K8JU8uQxefXGyqekbjsk0IxXk4QSZjXiOWUDWfg34VPkwCFe8Meu2w40EA==
# SIG # End signature block