Functions.Autorest/custom/New-AzFunctionApp.ps1
|
function New-AzFunctionApp { [Microsoft.Azure.PowerShell.Cmdlets.Functions.Runtime.PreviewMessage("*******************************************************************************************`n * This cmdlet will undergo a breaking change in Az v16.0.0, to be released on May 2026. *`n * At least one change applies to this cmdlet. *`n * See all possible breaking changes at https://go.microsoft.com/fwlink/?linkid=2333486 *`n *******************************************************************************************")] [OutputType([Microsoft.Azure.PowerShell.Cmdlets.Functions.Models.ISite])] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Description('Creates a function app.')] [CmdletBinding(SupportsShouldProcess=$true, DefaultParametersetname="Consumption")] param( [Parameter(ParameterSetName="Consumption", HelpMessage='The Azure subscription ID.')] [Parameter(ParameterSetName="ByAppServicePlan")] [Parameter(ParameterSetName="CustomDockerImage")] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [Parameter(ParameterSetName="FlexConsumption")] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Runtime.DefaultInfo(Script='(Get-AzContext).Subscription.Id')] [ValidateNotNullOrEmpty()] [System.String] ${SubscriptionId}, [Parameter(Mandatory=$true, ParameterSetName="Consumption", HelpMessage='The name of the resource group.')] [Parameter(Mandatory=$true, ParameterSetName="ByAppServicePlan")] [Parameter(Mandatory=$true, ParameterSetName="CustomDockerImage")] [Parameter(Mandatory=$true, ParameterSetName="EnvironmentForContainerApp")] [Parameter(Mandatory=$true, ParameterSetName="FlexConsumption")] [ValidateNotNullOrEmpty()] [System.String] ${ResourceGroupName}, [Parameter(Mandatory=$true, ParameterSetName="Consumption", HelpMessage='The name of the function app.')] [Parameter(Mandatory=$true, ParameterSetName="ByAppServicePlan")] [Parameter(Mandatory=$true, ParameterSetName="CustomDockerImage")] [Parameter(Mandatory=$true, ParameterSetName="EnvironmentForContainerApp")] [Parameter(Mandatory=$true,ParameterSetName="FlexConsumption")] [ValidateNotNullOrEmpty()] [System.String] ${Name}, [Parameter(Mandatory=$true, ParameterSetName="Consumption", HelpMessage='The name of the storage account.')] [Parameter(Mandatory=$true, ParameterSetName="ByAppServicePlan")] [Parameter(Mandatory=$true, ParameterSetName="CustomDockerImage")] [Parameter(Mandatory=$true, ParameterSetName="EnvironmentForContainerApp")] [Parameter(Mandatory=$true, ParameterSetName="FlexConsumption")] [ValidateNotNullOrEmpty()] [System.String] ${StorageAccountName}, [Parameter(ParameterSetName="Consumption", HelpMessage='Name of the existing App Insights project to be added to the function app.')] [Parameter(ParameterSetName="ByAppServicePlan")] [Parameter(ParameterSetName="CustomDockerImage")] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [Parameter(ParameterSetName="FlexConsumption")] [ValidateNotNullOrEmpty()] [System.String] [Alias("AppInsightsName")] ${ApplicationInsightsName}, [Parameter(ParameterSetName="Consumption", HelpMessage='Instrumentation key of App Insights to be added.')] [Parameter(ParameterSetName="ByAppServicePlan")] [Parameter(ParameterSetName="CustomDockerImage")] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [Parameter(ParameterSetName="FlexConsumption")] [ValidateNotNullOrEmpty()] [System.String] [Alias("AppInsightsKey")] ${ApplicationInsightsKey}, [Parameter(Mandatory=$true, ParameterSetName="Consumption", HelpMessage='The location for the consumption plan.')] [ValidateNotNullOrEmpty()] [System.String] ${Location}, [Parameter(Mandatory=$true, ParameterSetName="ByAppServicePlan", HelpMessage='The name of the service plan.')] [Parameter(Mandatory=$true, ParameterSetName="CustomDockerImage")] [ValidateNotNullOrEmpty()] [System.String] ${PlanName}, [Parameter(ParameterSetName="ByAppServicePlan", HelpMessage='The OS to host the function app.')] [Parameter(ParameterSetName="Consumption")] [ArgumentCompleter([Microsoft.Azure.PowerShell.Cmdlets.Functions.Support.WorkerType])] [ValidateSet("Linux", "Windows")] [ValidateNotNullOrEmpty()] [System.String] # OS type (Linux or Windows) ${OSType}, [Parameter(Mandatory=$true, ParameterSetName="ByAppServicePlan", HelpMessage='The function runtime.')] [Parameter(Mandatory=$true, ParameterSetName="Consumption")] [Parameter(Mandatory=$true, ParameterSetName="FlexConsumption")] [ValidateNotNullOrEmpty()] [System.String] # Runtime types are defined in HelperFunctions.ps1 ${Runtime}, [Parameter(ParameterSetName="ByAppServicePlan", HelpMessage='The function runtime.')] [Parameter(ParameterSetName="Consumption")] [Parameter(ParameterSetName="FlexConsumption")] [ValidateNotNullOrEmpty()] [System.String] # RuntimeVersion types are defined in HelperFunctions.ps1 ${RuntimeVersion}, [Parameter(ParameterSetName="ByAppServicePlan", HelpMessage='The Functions version.')] [Parameter(ParameterSetName="Consumption")] [ValidateNotNullOrEmpty()] [System.String] # FunctionsVersion types are defined in HelperFunctions.ps1 ${FunctionsVersion}, [Parameter(ParameterSetName="ByAppServicePlan", HelpMessage='Disable creating application insights resource during the function app creation. No logs will be available.')] [Parameter(ParameterSetName="Consumption")] [Parameter(ParameterSetName="CustomDockerImage")] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [Parameter(ParameterSetName="FlexConsumption")] [System.Management.Automation.SwitchParameter] [Alias("DisableAppInsights")] ${DisableApplicationInsights}, [Parameter(Mandatory=$true, ParameterSetName="CustomDockerImage", HelpMessage='Container image name, e.g., publisher/image-name:tag.')] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [ValidateNotNullOrEmpty()] [System.String] [Alias("DockerImageName")] ${Image}, [Parameter(ParameterSetName="CustomDockerImage", HelpMessage='The container registry username and password. Required for private registries.')] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [ValidateNotNullOrEmpty()] [PSCredential] [Alias("DockerRegistryCredential")] ${RegistryCredential}, [Parameter(HelpMessage='Returns true when the command succeeds.')] [System.Management.Automation.SwitchParameter] ${PassThru}, [Parameter(ParameterSetName="ByAppServicePlan", HelpMessage='Starts the operation and returns immediately, before the operation is completed. In order to determine if the operation has successfully been completed, use some other mechanism.')] [Parameter(ParameterSetName="Consumption")] [Parameter(ParameterSetName="CustomDockerImage")] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [Parameter(ParameterSetName="FlexConsumption")] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Runtime')] [System.Management.Automation.SwitchParameter] ${NoWait}, [Parameter(ParameterSetName="ByAppServicePlan", HelpMessage='Runs the cmdlet as a background job.')] [Parameter(ParameterSetName="Consumption")] [Parameter(ParameterSetName="CustomDockerImage")] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [Parameter(ParameterSetName="FlexConsumption")] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Runtime')] [System.Management.Automation.SwitchParameter] ${AsJob}, [Parameter(ParameterSetName="ByAppServicePlan", HelpMessage='Resource tags.')] [Parameter(ParameterSetName="Consumption")] [Parameter(ParameterSetName="CustomDockerImage")] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [Parameter(ParameterSetName="FlexConsumption")] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Body')] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Runtime.Info(PossibleTypes=([Microsoft.Azure.PowerShell.Cmdlets.Functions.Models.IResourceTags]))] [System.Collections.Hashtable] [ValidateNotNull()] ${Tag}, [Parameter(ParameterSetName="ByAppServicePlan", HelpMessage='Function app settings.')] [Parameter(ParameterSetName="Consumption")] [Parameter(ParameterSetName="CustomDockerImage")] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [Parameter(ParameterSetName="FlexConsumption")] [ValidateNotNullOrEmpty()] [Hashtable] ${AppSetting}, [Parameter(ParameterSetName="ByAppServicePlan", HelpMessage="Determines whether to enable a system-assigned identity for the resource.")] [Parameter(ParameterSetName="Consumption")] [Parameter(ParameterSetName="CustomDockerImage")] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [Parameter(ParameterSetName="FlexConsumption")] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Body')] [System.Management.Automation.SwitchParameter] ${EnableSystemAssignedIdentity}, [Parameter(ParameterSetName="ByAppServicePlan", HelpMessage="The array of user assigned identities associated with the function app. The user identity references will be ARM resource ids in the form: '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{identityName}'")] [Parameter(ParameterSetName="Consumption")] [Parameter(ParameterSetName="CustomDockerImage")] [Parameter(ParameterSetName="EnvironmentForContainerApp")] [Parameter(ParameterSetName="FlexConsumption")] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Body')] [System.String[]] ${UserAssignedIdentity}, [Parameter(Mandatory=$true,ParameterSetName="FlexConsumption", HelpMessage='Location to create Flex Consumption function app.')] [ValidateNotNullOrEmpty()] [System.String] ${FlexConsumptionLocation}, [Parameter(ParameterSetName="FlexConsumption", HelpMessage='Name of deployment storage account to be used for function app artifacts.')] [ValidateNotNullOrEmpty()] [System.String] ${DeploymentStorageName}, [Parameter(ParameterSetName="FlexConsumption", HelpMessage='Deployment storage container name.')] [ValidateNotNullOrEmpty()] [System.String] ${DeploymentStorageContainerName}, [Parameter(ParameterSetName="FlexConsumption", HelpMessage='Deployment storage authentication type. Allowed values: StorageAccountConnectionString, SystemAssignedIdentity, UserAssignedIdentity')] [ValidateSet("StorageAccountConnectionString", "SystemAssignedIdentity", "UserAssignedIdentity")] [ValidateNotNullOrEmpty()] [System.String] ${DeploymentStorageAuthType}, [Parameter(ParameterSetName="FlexConsumption", HelpMessage='Deployment storage authentication value used for the chosen auth type (eg: connection string, or user-assigned identity resource id).')] [System.String] [ValidateNotNullOrEmpty()] ${DeploymentStorageAuthValue}, [Parameter(ParameterSetName="FlexConsumption", HelpMessage= 'Array of hashtables describing the AlwaysReady configuration. Each hashtable must include: - name: The function name or route name. - instanceCount: The number of pre-warmed instances for that function. Example: @(@{ name = "http"; instanceCount = 2 }).')] [ValidateNotNullOrEmpty()] [Hashtable[]] ${AlwaysReady}, [Parameter(ParameterSetName="FlexConsumption", HelpMessage='Maximum instance count for Flex Consumption.')] [ValidateRange(40, 1000)] [int] ${MaximumInstanceCount}, [Parameter(ParameterSetName="FlexConsumption", HelpMessage='Per-instance memory in MB for Flex Consumption instances.')] [ValidateSet(512, 2048, 4096)] [int] ${InstanceMemoryMB}, [Parameter(ParameterSetName="FlexConsumption", HelpMessage='The maximum number of concurrent HTTP trigger invocations per instance.')] [ValidateRange(1, 1000)] [int] ${HttpPerInstanceConcurrency}, [Parameter(ParameterSetName="FlexConsumption", HelpMessage='Enable zone redundancy for high availability. Applies to Flex Consumption SKU only.')] [System.Management.Automation.SwitchParameter] ${EnableZoneRedundancy}, [Parameter(Mandatory=$true, ParameterSetName="EnvironmentForContainerApp", HelpMessage='Name of the container app environment.')] [ValidateNotNullOrEmpty()] [System.String] ${Environment}, [Parameter(Mandatory=$false, ParameterSetName="EnvironmentForContainerApp", HelpMessage='The workload profile name to run the container app on.')] [ValidateNotNullOrEmpty()] [System.String] ${WorkloadProfileName}, [Parameter(Mandatory=$false, ParameterSetName="EnvironmentForContainerApp", HelpMessage='The CPU in cores of the container app. e.g., 0.75.')] [ValidateNotNullOrEmpty()] [Double] ${ResourceCpu}, [Parameter(Mandatory=$false, ParameterSetName="EnvironmentForContainerApp", HelpMessage='The memory size of the container app. e.g., 1.0Gi.')] [ValidateNotNullOrEmpty()] [System.String] ${ResourceMemory}, [Parameter(Mandatory=$false, ParameterSetName="EnvironmentForContainerApp", HelpMessage='The maximum number of replicas when creating a function app on container app.')] [ValidateScript({$_ -gt 0})] [Int] ${ScaleMaxReplica}, [Parameter(Mandatory=$false, ParameterSetName="EnvironmentForContainerApp", HelpMessage='The minimum number of replicas when create function app on container app.')] [ValidateScript({$_ -gt 0})] [Int] ${ScaleMinReplica}, [Parameter(Mandatory=$false, ParameterSetName="EnvironmentForContainerApp", HelpMessage='The container registry server hostname, e.g. myregistry.azurecr.io.')] [ValidateNotNullOrEmpty()] [System.String] ${RegistryServer}, [Parameter(HelpMessage='The credentials, account, tenant, and subscription used for communication with Azure.')] [Alias('AzureRMContext', 'AzureCredential')] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Azure')] [System.Management.Automation.PSObject] ${DefaultProfile}, [Parameter(DontShow)] [System.Management.Automation.SwitchParameter] ${Break}, [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Runtime')] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Runtime.SendAsyncStep[]] # SendAsync Pipeline Steps to be appended to the front of the pipeline ${HttpPipelineAppend}, [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Runtime')] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Runtime.SendAsyncStep[]] # SendAsync Pipeline Steps to be prepended to the front of the pipeline ${HttpPipelinePrepend}, [Parameter(DontShow)] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Runtime')] [System.Uri] # The URI for the proxy server to use ${Proxy}, [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Runtime')] [System.Management.Automation.PSCredential] # Credentials for a proxy server to use for the remote call ${ProxyCredential}, [Parameter(DontShow)] [Microsoft.Azure.PowerShell.Cmdlets.Functions.Category('Runtime')] [System.Management.Automation.SwitchParameter] # Use the default credentials for the proxy ${ProxyUseDefaultCredentials} ) process { RegisterFunctionsTabCompleters # Remove bound parameters from the dictionary that cannot be process by the intenal cmdlets. $paramsToRemove = @( "StorageAccountName", "ApplicationInsightsName", "ApplicationInsightsKey", "Location", "PlanName", "OSType", "Runtime", "DisableApplicationInsights", "Image", "RegistryCredential", "FunctionsVersion", "RuntimeVersion", "AppSetting", "Tag", "Environment", "RegistryServer", "WorkloadProfileName", "ResourceCpu", "ResourceMemory", "ScaleMaxReplica", "ScaleMinReplica", "FlexConsumptionLocation", "DeploymentStorageName", "DeploymentStorageContainerName", "DeploymentStorageAuthType", "DeploymentStorageAuthValue", "AlwaysReady", "MaximumInstanceCount", "InstanceMemoryMB", "HttpPerInstanceConcurrency", "EnableZoneRedundancy", "EnableSystemAssignedIdentity", "UserAssignedIdentity" ) foreach ($paramName in $paramsToRemove) { if ($PSBoundParameters.ContainsKey($paramName)) { $PSBoundParameters.Remove($paramName) | Out-Null } } $functionAppIsCustomDockerImage = $PsCmdlet.ParameterSetName -eq "CustomDockerImage" $environmentForContainerApp = $PsCmdlet.ParameterSetName -eq "EnvironmentForContainerApp" $consumptionPlan = $PsCmdlet.ParameterSetName -eq "Consumption" $functionAppIsFlexConsumption = $PsCmdlet.ParameterSetName -eq "FlexConsumption" $flexConsumptionStorageContainerCreated = $false $flexConsumptionPlanCreated = $false $appInsightCreated = $false $functionAppCreatedSuccessfully = $false $appSettings = New-Object -TypeName System.Collections.Generic.List[Microsoft.Azure.PowerShell.Cmdlets.Functions.Models.INameValuePair] $siteConfig = New-Object -TypeName Microsoft.Azure.PowerShell.Cmdlets.Functions.Models.SiteConfig $functionAppDef = New-Object -TypeName Microsoft.Azure.PowerShell.Cmdlets.Functions.Models.Site $OSIsLinux = ($OSType -eq "Linux") -or $functionAppIsFlexConsumption $params = GetParameterKeyValues -PSBoundParametersDictionary $PSBoundParameters ` -ParameterList @("SubscriptionId", "HttpPipelineAppend", "HttpPipelinePrepend") ValidateFunctionAppNameAvailability -Name $Name @params $runtimeJsonDefinition = $null if (-not ($functionAppIsCustomDockerImage -or $environmentForContainerApp -or $functionAppIsFlexConsumption)) { if (-not $FunctionsVersion) { $FunctionsVersion = $DefaultFunctionsVersion Write-Warning "FunctionsVersion not specified. Setting default value to '$FunctionsVersion'. $SetDefaultValueParameterWarningMessage" } ValidateFunctionsVersion -FunctionsVersion $FunctionsVersion if (-not $OSType) { $OSType = GetDefaultOSType -Runtime $Runtime Write-Warning "OSType not specified. Setting default value to '$OSType'. $SetDefaultValueParameterWarningMessage" } $runtimeJsonDefinition = GetStackDefinitionForRuntime -FunctionsVersion $FunctionsVersion -Runtime $Runtime -RuntimeVersion $RuntimeVersion -OSType $OSType if (-not $runtimeJsonDefinition) { $errorId = "FailedToGetRuntimeDefinition" $message += "Failed to get runtime definition for '$Runtime' version '$RuntimeVersion' in Functions version '$FunctionsVersion' on '$OSType'." $exception = [System.InvalidOperationException]::New($message) ThrowTerminatingError -ErrorId $errorId ` -ErrorMessage $message ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } # Add app settings if ($runtimeJsonDefinition.AppSettingsDictionary.Count -gt 0) { foreach ($keyName in $runtimeJsonDefinition.AppSettingsDictionary.Keys) { $value = $runtimeJsonDefinition.AppSettingsDictionary[$keyName] $appSettings.Add((NewAppSetting -Name $keyName -Value $value)) } } # Add site config properties if ($runtimeJsonDefinition.SiteConfigPropertiesDictionary.Count -gt 0) { foreach ($PropertyName in $runtimeJsonDefinition.SiteConfigPropertiesDictionary.Keys) { $value = $runtimeJsonDefinition.SiteConfigPropertiesDictionary[$PropertyName] $siteConfig.$PropertyName = $value } } } # Set function app managed identity if ($null -ne $UserAssignedIdentity -and $UserAssignedIdentity.Count -eq 0) { $errorMessage = "At least one user-assigned identity resource ID must be provided via the -UserAssignedIdentity parameter." $exception = [System.InvalidOperationException]::New($errorMessage) ThrowTerminatingError -ErrorId "UserAssignedIdentityRequired" ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } # Validate that each identity ID is non-empty/non-whitespace if ($UserAssignedIdentity) { foreach ($id in $UserAssignedIdentity) { if ([string]::IsNullOrWhiteSpace($id)) { $errorMessage = "User-assigned identity resource IDs must not be null, empty, or whitespace." $exception = [System.InvalidOperationException]::New($errorMessage) ThrowTerminatingError -ErrorId "UserAssignedIdentityRequired" ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } } } if ($EnableSystemAssignedIdentity.IsPresent -and $UserAssignedIdentity) { $functionAppDef.IdentityType = "SystemAssigned,UserAssigned" $identityUserAssignedIdentity = NewIdentityUserAssignedIdentity -IdentityID $UserAssignedIdentity $functionAppDef.IdentityUserAssignedIdentity = $identityUserAssignedIdentity } elseif ($EnableSystemAssignedIdentity.IsPresent) { $functionAppDef.IdentityType = "SystemAssigned" } elseif ($UserAssignedIdentity) { $functionAppDef.IdentityType = "UserAssigned" $identityUserAssignedIdentity = NewIdentityUserAssignedIdentity -IdentityID $UserAssignedIdentity $functionAppDef.IdentityUserAssignedIdentity = $identityUserAssignedIdentity } $servicePlan = $null $dockerRegistryServerUrl = $null if ($consumptionPlan) { ValidateConsumptionPlanLocation -Location $Location -OSIsLinux:$OSIsLinux @params $functionAppDef.Location = $Location } elseif ($environmentForContainerApp) { $OSIsLinux = $true if (-not $Image) { Write-Warning "Image not specified. Setting default value to '$DefaultCentauriImage'." $Image = $DefaultCentauriImage } if ($RegistryServer) { $dockerRegistryServerUrl = $RegistryServer } if ($Environment -and $RegistryCredential) { # Error out if the user has specified both Environment and RegistryCredential and not provided RegistryServer. if (-not $RegistryServer) { $errorMessage = "RegistryServer is required when Environment and RegistryCredential is specified." $exception = [System.InvalidOperationException]::New($errorMessage) ThrowTerminatingError -ErrorId "RegistryServerRequired" ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } } } elseif ($PlanName) { # Host function app in Elastic Premium or app service plan $servicePlan = GetServicePlan $PlanName @params if ($null -ne $servicePlan.Location) { $Location = $servicePlan.Location } if ($null -ne $servicePlan.Reserved) { $OSIsLinux = $servicePlan.Reserved } $functionAppDef.ServerFarmId = $servicePlan.Id $functionAppDef.Location = $Location } if ($OSIsLinux) { # These are the scenarios we currently support when creating a Docker container: # 1) In Consumption, we only support images created by Functions with a predefine runtime name and version, e.g., Python 3.7 # 2) For App Service and Premium plans, a customer can specify a customer container image # Linux function app $functionAppDef.Kind = 'functionapp,linux' $functionAppDef.Reserved = $true # Bring your own container is only supported on App Service, Premium plans and Container App if ($Image) { $functionAppDef.Kind = 'functionapp,linux,container' $appSettings.Add((NewAppSetting -Name 'DOCKER_CUSTOM_IMAGE_NAME' -Value $Image.Trim().ToLower())) $appSettings.Add((NewAppSetting -Name 'FUNCTION_APP_EDIT_MODE' -Value 'readOnly')) $appSettings.Add((NewAppSetting -Name 'WEBSITES_ENABLE_APP_SERVICE_STORAGE' -Value 'false')) $siteConfig.LinuxFxVersion = FormatFxVersion -Image $Image # Parse the docker registry url only for the custom image parameter set (otherwise it will be a breaking change for existing customers). # For the container app environment, the registry url must me explicitly provided. if (-not $dockerRegistryServerUrl -and -not $environmentForContainerApp) { $dockerRegistryServerUrl = ParseDockerImage -DockerImageName $Image } if ($dockerRegistryServerUrl) { $appSettings.Add((NewAppSetting -Name 'DOCKER_REGISTRY_SERVER_URL' -Value $dockerRegistryServerUrl)) if ($RegistryCredential) { $appSettings.Add((NewAppSetting -Name 'DOCKER_REGISTRY_SERVER_USERNAME' -Value $RegistryCredential.GetNetworkCredential().UserName)) $appSettings.Add((NewAppSetting -Name 'DOCKER_REGISTRY_SERVER_PASSWORD' -Value $RegistryCredential.GetNetworkCredential().Password)) } } } else { if (-not $functionAppIsFlexConsumption) { $appSettings.Add((NewAppSetting -Name 'WEBSITES_ENABLE_APP_SERVICE_STORAGE' -Value 'true')) } } } else { # Windows function app $functionAppDef.Kind = 'functionapp' } if ($environmentForContainerApp) { $functionAppDef.Kind = 'functionapp,linux,container,azurecontainerapps' $functionAppDef.Reserved = $null $functionAppDef.HttpsOnly = $null $functionAppDef.ScmSiteAlsoStopped = $null ValidateCpuAndMemory -ResourceCpu $ResourceCpu -ResourceMemory $ResourceMemory if ($ResourceCpu -and $ResourceMemory) { $functionAppDef.ResourceConfigCpu = $ResourceCpu $functionAppDef.ResourceConfigMemory = $ResourceMemory } if ($WorkloadProfileName) { $functionAppDef.WorkloadProfileName = $WorkloadProfileName } $siteConfig.netFrameworkVersion = $null $siteConfig.JavaVersion = $null $siteConfig.Use32BitWorkerProcess = $null $siteConfig.PowerShellVersion = $null $siteConfig.Http20Enabled = $null $siteConfig.LocalMySqlEnabled = $null if ($ScaleMinReplica) { $siteConfig.MinimumElasticInstanceCount = $ScaleMinReplica } if ($ScaleMaxReplica) { $siteConfig.FunctionAppScaleLimit = $ScaleMaxReplica } $managedEnvironment = GetManagedEnvironment -Environment $Environment -ResourceGroupName $ResourceGroupName $functionAppDef.Location = $managedEnvironment.Location $functionAppDef.ManagedEnvironmentId = $managedEnvironment.Id } try { if ($functionAppIsFlexConsumption) { # Reset properties not applicable for Flex Consumption $siteConfig.NetFrameworkVersion = $null $functionAppDef.Reserved = $null $functionAppDef.IsXenon = $null $appSettings.Clear() # Validate Flex Consumption location Validate-FlexConsumptionLocation -Location $FlexConsumptionLocation -ZoneRedundancy:$EnableZoneRedundancy $FlexConsumptionLocation = Format-FlexConsumptionLocation -Location $FlexConsumptionLocation # Validate runtime and runtime version if (-not ($FlexConsumptionSupportedRuntimes -contains $Runtime)) { $errorId = "InvalidRuntimeForFlexConsumption" $message += "The specified Runtime '$Runtime' is not valid for Flex Consumption. " $message += "Supported runtimes are: $($FlexConsumptionSupportedRuntimes -join ', '). Learn more about supported runtimes and versions for Flex Consumption: aka.ms/FunctionsStackUpgrade." $exception = [System.InvalidOperationException]::New($message) ThrowTerminatingError -ErrorId $errorId ` -ErrorMessage $message ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } $runtimeInfo = $null $hasDefaultVersion = $false if ([string]::IsNullOrEmpty($RuntimeVersion)) { $runtimeInfo = Get-FlexFunctionAppRuntime -Location $FlexConsumptionLocation -Runtime $Runtime -DefaultOrLatest:$true $hasDefaultVersion = $true $RuntimeVersion = $runtimeInfo.Version Write-Warning "RuntimeVersion not specified. Setting default value to '$RuntimeVersion'. $SetDefaultValueParameterWarningMessage" } else { # Get runtime info for specified version. If not available, Get-FlexFunctionAppRuntime will error out. $runtimeInfo = Get-FlexFunctionAppRuntime -Location $FlexConsumptionLocation -Runtime $Runtime -Version $RuntimeVersion } # Validate EndOfLifeDate if ($runtimeInfo.EndOfLifeDate -and (-not $hasDefaultVersion)) { $defaultRuntimeInfo = Get-FlexFunctionAppRuntime -Location $FlexConsumptionLocation -Runtime $Runtime -DefaultOrLatest:$true Validate-EndOfLifeDate -EndOfLifeDate $runtimeInfo.EndOfLifeDate ` -Runtime $Runtime ` -RuntimeVersion $RuntimeVersion ` -DefaultRuntimeVersion $defaultRuntimeInfo.Version } # Validate and set AlwaysReady configuration if ($AlwaysReady -and $AlwaysReady.Count -gt 0) { $ALWAYSREADY_NAME = 'name' $ALWAYSREADY_INSTANCECOUNT = 'instanceCount' foreach ($entry in $AlwaysReady) { # Ensure required keys exist if (-not ($entry.ContainsKey($ALWAYSREADY_NAME) -and $entry.ContainsKey($ALWAYSREADY_INSTANCECOUNT))) { $errorMessage = "Each hashtable in AlwaysReady must contain '$ALWAYSREADY_NAME' and '$ALWAYSREADY_INSTANCECOUNT' keys." $exception = [System.InvalidOperationException]::New($errorMessage) ThrowTerminatingError -ErrorId "InvalidAlwaysReadyConfiguration" ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } # Validate that Name is a non-empty string if ([string]::IsNullOrWhiteSpace($entry[$ALWAYSREADY_NAME])) { $errorMessage = "Name in AlwaysReady must be a non-empty string." $exception = [System.InvalidOperationException]::New($errorMessage) ThrowTerminatingError -ErrorId "InvalidAlwaysReadyName" ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } # Validate InstanceCount is a non-negative integer (single-parse + combined check) [int]$parsedInstanceCount = 0 $rawInstanceCount = $entry[$ALWAYSREADY_INSTANCECOUNT] if (-not ([int]::TryParse($rawInstanceCount, [ref]$parsedInstanceCount) -and $parsedInstanceCount -ge 0)) { $errorMessage = "InstanceCount in AlwaysReady must be a non-negative integer." $exception = [System.InvalidOperationException]::new($errorMessage) ThrowTerminatingError -ErrorId "InvalidAlwaysReadyInstanceCount" ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } } $functionAppDef.ScaleAndConcurrencyAlwaysReady = $AlwaysReady } # Set scaling information $maximumInstanceCountValue = Validate-MaximumInstanceCount -SkuMaximumInstanceCount $runtimeInfo.Sku.maximumInstanceCount -MaximumInstanceCount $MaximumInstanceCount $functionAppDef.ScaleAndConcurrencyMaximumInstanceCount = $maximumInstanceCountValue $instanceMemoryMBValue = Validate-InstanceMemoryMB -SkuInstanceMemoryMB $runtimeInfo.Sku.instanceMemoryMB -InstanceMemoryMB $InstanceMemoryMB $functionAppDef.ScaleAndConcurrencyInstanceMemoryMB = $instanceMemoryMBValue if ($HttpPerInstanceConcurrency -gt 0) { $functionAppDef.HttpPerInstanceConcurrency = $HttpPerInstanceConcurrency } # Create Flex Consumption App Service Plan $planName = New-PlanName -ResourceGroupName $ResourceGroupName if ($WhatIfPreference.IsPresent) { Write-Verbose "WhatIf: Creating Flex Consumption App Service Plan '$planName' in resource group '$ResourceGroupName' at location '$FlexConsumptionLocation'..." $planInfo = New-Object PSObject -Property @{ Id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/$ResourceGroupName/providers/Microsoft.Web/serverfarms/$planName" } } else { $planInfo = New-FlexConsumptionAppPlan -Name $PlanName ` -ResourceGroupName $ResourceGroupName ` -Location $FlexConsumptionLocation ` -EnableZoneRedundancy:$EnableZoneRedundancy ` @params $flexConsumptionPlanCreated = $true } $functionAppDef.ServerFarmId = $planInfo.Id $functionAppDef.Location = $FlexConsumptionLocation # Validate Deployment Storage if (-not $DeploymentStorageName) { $DeploymentStorageName = $StorageAccountName } if (-not $DeploymentStorageContainerName) { $useTestData = ($env:FunctionsTestMode -and $env:FunctionsUseFlexStackTestData) # Generate a unique container name $tempName = $Name -replace '[^a-zA-Z0-9]', '' $normalizedName = $tempName.Substring(0, [Math]::Min(32, $tempName.Length)) $normalizedName = $normalizedName.ToLower() if ($useTestData) { $randomSuffix = 0 } else { $randomSuffix = Get-Random -Minimum 0 -Maximum 9999999 } $DeploymentStorageContainerName = "app-package-$normalizedName-{0:D7}" -f $randomSuffix if ($useTestData) { Write-Verbose "Setting DeploymentStorageContainerName to: '$DeploymentStorageContainerName'." -Verbose } } $StorageAccountInfo = Get-StorageAccountInfo -Name $DeploymentStorageName @params # If container does not exist, create it $container = Az.Functions.internal\Get-AzBlobContainer -ContainerName $DeploymentStorageContainerName ` -AccountName $DeploymentStorageName ` -ResourceGroupName $ResourceGroupName ` -ErrorAction SilentlyContinue ` @params if (-not $container) { if ($WhatIfPreference.IsPresent) { Write-Verbose "WhatIf: Creating container '$DeploymentStorageContainerName' in storage account '$DeploymentStorageName'..." $container = New-Object -TypeName Microsoft.Azure.PowerShell.Cmdlets.Functions.Models.BlobContainer } else { # Create blob container $maxNumberOfTries = 3 $tries = 1 $myError = $null while ($true) { try { $container = Az.Functions.internal\New-AzBlobContainer -ContainerName $DeploymentStorageContainerName ` -AccountName $DeploymentStorageName ` -ResourceGroupName $ResourceGroupName ` -ContainerPropertyPublicAccess None ` -ErrorAction Stop ` @params if ($container) { $flexConsumptionStorageContainerCreated = $true break } } catch { # Ignore the failure and continue $myError = $_ } if ($tries -ge $maxNumberOfTries) { break } # Wait for 2^(tries-1) seconds between retries. In this case, it would be 1, 2, and 4 seconds, respectively. $waitInSeconds = [Math]::Pow(2, $tries - 1) Start-Sleep -Seconds $waitInSeconds $tries++ } if (-not $container) { $errorMessage = "Failed to create blob container '$DeploymentStorageContainerName' in storage account '$DeploymentStorageName'." if ($myError.Exception.Message) { $errorMessage += " Error details: $($myError.Exception.Message)" } $exception = [System.InvalidOperationException]::New($errorMessage) ThrowTerminatingError -ErrorId "FailedToCreateBlobContainer" ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } } } # Set storage type and value $blobContainerUrl = "$($StorageAccountInfo.PrimaryEndpointBlob)$DeploymentStorageContainerName" $functionAppDef.StorageType = "blobContainer" $functionAppDef.StorageValue = $blobContainerUrl # Validate DeploymentStorageAuthType if (-not $DeploymentStorageAuthType) { $DeploymentStorageAuthType = 'StorageAccountConnectionString' } $functionAppDef.AuthenticationType = $DeploymentStorageAuthType # Set deployment storage authentication if ($DeploymentStorageAuthType -eq "SystemAssignedIdentity") { if ($DeploymentStorageAuthValue) { $errorMessage = "-DeploymentStorageAuthValue is only valid when -DeploymentStorageAuthType is UserAssignedIdentity or StorageAccountConnectionString." $exception = [System.InvalidOperationException]::New($errorMessage) ThrowTerminatingError -ErrorId $errorId ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } } elseif ($DeploymentStorageAuthType -eq "StorageAccountConnectionString") { if (-not $DeploymentStorageAuthValue) { # Get connection string for deployment storage $DeploymentStorageAuthValue = GetConnectionString -StorageAccountName $DeploymentStorageName @params } $DEPLOYMENT_STORAGE_CONNECTION_STRING = 'DEPLOYMENT_STORAGE_CONNECTION_STRING' $functionAppDef.AuthenticationStorageAccountConnectionStringName = $DEPLOYMENT_STORAGE_CONNECTION_STRING $appSettings.Add((NewAppSetting -Name $DEPLOYMENT_STORAGE_CONNECTION_STRING -Value $DeploymentStorageAuthValue)) } elseif ($DeploymentStorageAuthType -eq "UserAssignedIdentity") { if (-not $DeploymentStorageAuthValue) { $errorMessage = "IdentityID is required for UserAssigned identity" $exception = [System.InvalidOperationException]::New($errorMessage) ThrowTerminatingError -ErrorId "IdentityIDIsRequiredForUserAssignedIdentity" ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } $identity = Resolve-UserAssignedIdentity -IdentityResourceId $DeploymentStorageAuthValue @params $functionAppDef.AuthenticationUserAssignedIdentityResourceId = $identity.Id } # Set runtime information $functionAppDef.RuntimeName = $runtimeInfo.Sku.functionAppConfigProperties.runtime.name $functionAppDef.RuntimeVersion = $runtimeInfo.Sku.functionAppConfigProperties.runtime.version } # Validate storage account and get connection string $connectionString = GetConnectionString -StorageAccountName $StorageAccountName @params $appSettings.Add((NewAppSetting -Name 'AzureWebJobsStorage' -Value $connectionString)) if (-not ($functionAppIsCustomDockerImage -or $environmentForContainerApp -or $functionAppIsFlexConsumption)) { $appSettings.Add((NewAppSetting -Name 'FUNCTIONS_EXTENSION_VERSION' -Value "~$FunctionsVersion")) } # If plan is not consumption, elastic premium or a container app environment, set always on $planIsElasticPremium = $servicePlan.SkuTier -eq 'ElasticPremium' if ((-not $consumptionPlan) -and (-not $planIsElasticPremium) -and (-not $Environment) -and (-not $functionAppIsFlexConsumption)) { $siteConfig.AlwaysOn = $true } # If plan is Elastic Premium or Consumption (Windows or Linux), we need these app settings if ($planIsElasticPremium -or $consumptionPlan) { $appSettings.Add((NewAppSetting -Name 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' -Value $connectionString)) $shareName = GetShareName -FunctionAppName $Name $appSettings.Add((NewAppSetting -Name 'WEBSITE_CONTENTSHARE' -Value $shareName)) } # Set up Dashboard if no ApplicationInsights if ($DisableApplicationInsights -and (-not $functionAppIsFlexConsumption)) { $appSettings.Add((NewAppSetting -Name 'AzureWebJobsDashboard' -Value $connectionString)) } # Set up Application Insights if (-not $DisableApplicationInsights) { if ($ApplicationInsightsKey) { $appSettings.Add((NewAppSetting -Name 'APPINSIGHTS_INSTRUMENTATIONKEY' -Value $ApplicationInsightsKey)) } elseif ($ApplicationInsightsName) { $appInsightsProject = GetApplicationInsightsProject -Name $ApplicationInsightsName @params if (-not $appInsightsProject) { $errorMessage = "Failed to get application insights project name '$ApplicationInsightsName'. Please make sure the project exist." $exception = [System.InvalidOperationException]::New($errorMessage) ThrowTerminatingError -ErrorId "ApplicationInsightsProjectNotFound" ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } $appSettings.Add((NewAppSetting -Name 'APPLICATIONINSIGHTS_CONNECTION_STRING' -Value $appInsightsProject.ConnectionString)) } else { if ($WhatIfPreference.IsPresent) { Write-Verbose "WhatIf: Creating Application Insights '$Name' in resource group '$ResourceGroupName' at location '$($functionAppDef.Location)'..." # Create a mock object for WhatIf to avoid null reference issues $newAppInsightsProject = New-Object PSObject -Property @{ ConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://placeholder.applicationinsights.azure.com/" Name = $Name } $appSettings.Add((NewAppSetting -Name 'APPLICATIONINSIGHTS_CONNECTION_STRING' -Value $newAppInsightsProject.ConnectionString)) } else { # Create the Application Insights project $newAppInsightsProject = CreateApplicationInsightsProject -ResourceGroupName $resourceGroupName ` -ResourceName $Name ` -Location $functionAppDef.Location ` @params if ($newAppInsightsProject) { $appSettings.Add((NewAppSetting -Name 'APPLICATIONINSIGHTS_CONNECTION_STRING' -Value $newAppInsightsProject.ConnectionString)) $appInsightCreated = $true } else { $warningMessage = "Unable to create the Application Insights for the function app. Creation of Application Insights will help you monitor and diagnose your function apps in the Azure Portal. `r`n" $warningMessage += "Use the 'New-AzApplicationInsights' cmdlet or the Azure Portal to create a new Application Insights project. After that, use the 'Update-AzFunctionApp' cmdlet to update Application Insights for your function app." Write-Warning $warningMessage } } } } if ($Tag.Count -gt 0) { $resourceTag = NewResourceTag -Tag $Tag $functionAppDef.Tag = $resourceTag } # Add user app settings if ($AppSetting.Count -gt 0) { foreach ($keyName in $AppSetting.Keys) { $appSettings.Add((NewAppSetting -Name $keyName -Value $AppSetting[$keyName])) } } # Set app settings and site configuration $siteConfig.AppSetting = $appSettings $functionAppDef.Config = $siteConfig $PSBoundParameters.Add("SiteEnvelope", $functionAppDef) | Out-Null if ($PsCmdlet.ShouldProcess($Name, "Creating function app")) { # Save the ErrorActionPreference $currentErrorActionPreference = $ErrorActionPreference $ErrorActionPreference = 'Stop' $exceptionThrown = $false try { Az.Functions.internal\New-AzFunctionApp @PSBoundParameters $functionAppCreatedSuccessfully = $true } catch { $exceptionThrown = $true $errorMessage = GetErrorMessage -Response $_ if ($errorMessage) { $exception = [System.InvalidOperationException]::New($errorMessage) ThrowTerminatingError -ErrorId "FailedToCreateFunctionApp" ` -ErrorMessage $errorMessage ` -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) ` -Exception $exception } throw $_ } finally { # Reset the ErrorActionPreference $ErrorActionPreference = $currentErrorActionPreference } if (-not $exceptionThrown) { if ($consumptionPlan -and $OSIsLinux) { $message = "Your Linux function app '$Name', that uses a consumption plan has been successfully created but is not active until content is published using Azure Portal or the Functions Core Tools." Write-Verbose $message -Verbose } } } } finally { # Cleanup created resources in case of failure if (-not $functionAppCreatedSuccessfully) { if ($flexConsumptionPlanCreated) { Az.Functions\Remove-AzFunctionAppPlan -ResourceGroupName $ResourceGroupName -Name $planName @params -Force } if ($flexConsumptionStorageContainerCreated) { Az.Functions.internal\Remove-AzBlobContainer -ResourceGroupName $ResourceGroupName -AccountName $DeploymentStorageName -ContainerName $DeploymentStorageContainerName @params } if ($appInsightCreated -and ($null -ne $newAppInsightsProject)) { $ApplicationInsightsName = $newAppInsightsProject.Name Az.Functions.internal\Remove-AzAppInsights -ResourceGroupName $ResourceGroupName -ResourceName $ApplicationInsightsName @params } } } } } # SIG # Begin signature block # MIInSQYJKoZIhvcNAQcCoIInOjCCJzYCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCHC3VQOsdRM8Zf # BMGwrlCxzKOHpW8B2o31mpLt/63enKCCDLowggX1MIID3aADAgECAhMzAAACHU0Z # yE7XD1dIAAAAAAIdMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD # b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQzWhcNMjcwNDE1MTg1 # OTQzWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYD # VQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IB # DwAwggEKAoIBAQDQvewXxx9gZZFC6Ys1WBay8BJ8kGA4JQnH5CMafqOASlTpK9H8 # o5ZXTXt0caVQTNMUPt445wXYD+dFtaKWTwDn1I52oUSrC9vJin1Gsqt+zyKJL5Dg # 3eQXbQNR61DmMy20GLTIO3SFed9Rfi/ophgCLGFLDR3r0KvHjwMb/jYWS0celV/4 # Lz27LfAekm8v9E5IXaeiXbAUYZKK090n4CVl3JBtbN+9DtI9SNu/yjvozW52/u7R # X/Ttpa/KDlpuokZ+Zcbvmtd9ur9gFLvZzh41o9MsE/clQtdaFWGvuo6Jua/ntpgk # ey3E5/vBFe+MJPG6phdnuo6r57ZudCudiI1bAgMBAAGjggGbMIIBlzAOBgNVHQ8B # Af8EBAMCB4AwHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0O # BBYEFH6QuMwqcPG0hQlQ6c5jCtTTLrVeMEUGA1UdEQQ+MDykOjA4MR4wHAYDVQQL # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xFjAUBgNVBAUTDTIzMDAxMis1MDc1NTkw # HwYDVR0jBBgwFoAUf1k/VCHarU/vBeXmo9ctBpQSCDEwYAYDVR0fBFkwVzBVoFOg # UYZPaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0 # JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNybDBtBggrBgEFBQcBAQRh # MF8wXQYIKwYBBQUHMAKGUWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv # Y2VydHMvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNy # dDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQBKTbYOjzwTG/DXGaz9 # s6+fQeaTtDcFmMY+5UyVFCyj7Pv+5i37qfX8lSL/tBIfYQfWsMuBQlfZurJD6r4H # VJ2CeH+1fgiq8dcHdVKoZ3Sa2qXoX3cq9iS8cVb06B7+5/XJ7I0OxHH9fDsvJ3T3 # w5V/ZtAIFmLrl+P0CtG+92uzRsn0nTbdFjOkLMLWPLAU3THohKRlSEMgFJpPkm5n # 5UAZ35xX6FWCrDLsSKb555bTifwa8mJBwdlof0bmfYidH+dxZ1FdDxvLnNl9zeKs # A4kejaaIqqIPguhwAti5Ql7BlTNoJNwxCvBmqW2MQLnCkYN/VVUsR3V2x/rcTNzo # Bf/Z/SpROvdaA2ZOOd1uioXJt3tdLQ7vHpqpib0KfWr/FWXW10q38VxfCnRQBqzb # SuztR7nEMuzX7Ck+B/XaPDXd1qh72+QYyB0Z2VzWmO9zsnb9Uq/dwu8LGeQqnyu6 # 7SDGACvnXii2fb9+US492VTnXSnFKyqwgzUyFMtZK1/sHYTv6bG4TtQUygQxTN+Z # V+aJIlKO2MqZ7bKrAnOzS9m6NgoTdWOq11bTOZwKlIEV/EhV9SWkDmdpR/hPPT2v # 6TEj4F8PT/zHjRezIU5c/DGlt/VhY/pK0XkJtEyMmmS1BMtjU/rqBZVMIm3dnxQs # /TBByr+Cf8Z1r7aifQVQ+WSqzjCCBr0wggSloAMCAQICEzMAAAA5O7Y3Gb8GHWcA # AAAAADkwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRl # IEF1dGhvcml0eSAyMDExMB4XDTI0MDgwODIwNTQxOFoXDTM2MDMyMjIyMTMwNFow # VzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEo # MCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAyNDCCAiIwDQYJ # KoZIhvcNAQEBBQADggIPADCCAgoCggIBANgBnB7jOMeqlRYHNa265v4IY9fH8TKh # emHfPINe1gpLaV3dhg324WwH06LcHbpnsBukCDNitryo0dtS/EW6I/yEL/bLSY8h # KpbfQuWusBPr9qazYcDxCW/qnjb5JsI1s8bNOg3bVATvQVL4tcf03aTycsz8QeCd # M0l/yHRObJ9QqazM1r6VPEOJ7LL+uEEb73w6QCuhs89a1uv1zerOYMnsneRRwCbp # yW11IcggU0cRKDDq1pjVJzIbIF6+oiXXbReOsgeI8zu1FyQfK0fVkaya8SmVHQ/t # Of23mZ4W9k0Ri22QW9p3UgSC5OUDktKxxcCmGL6tXLfOGSWHIIV4YrTJTT6PNty5 # REojHJuZHArkF9VnHTERWoTjAzfI3kP+5b4alUdhgAZ7ttOu1bVnXfHaqPYl2rPs # 20ji03LOVWsh/radgE17es5hL+t6lV0eVHrVhsssROWJuz2MXMCt7iw7lFPG9LXK # Gjsmonn2gotGdHIuEg5JnJMJVmixd5LRlkmgYRZKzhxSCwyoGIq0PhaA7Y+VPct5 # pCHkijcIIDm0nlkK+0KyepolcqGm0T/GYQRMhHJlGOOmVQop36wUVUYklUy++vDW # eEgEo4s7hxN6mIbf2MSIQ/iIfMZgJxC69oukMUXCrOC3SkE/xIkgpfl22MM1itkZ # 35nNXkMolU1lAgMBAAGjggFOMIIBSjAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGC # NxUBBAMCAQAwHQYDVR0OBBYEFH9ZP1Qh2q1P7wXl5qPXLQaUEggxMBkGCSsGAQQB # gjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU # ci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2Ny # bC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0MjAx # MV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAwTgYIKwYBBQUHMAKGQmh0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0MjAx # MV8yMDExXzAzXzIyLmNydDANBgkqhkiG9w0BAQwFAAOCAgEAFJQfOChP7onn6fLI # MKrSlN1WYKwDFgAddymOUO3FrM8d7B/W/iQ6DxXsDn7D5W4wMwYeLystcEqfkjz4 # NURRgazyMu5yRzQh4LqjA4tStTcJh1opExo7nn5PuPBYnbu0+THSuVHTe0VTTPVh # ily/piFrDo3axQ9P4C+Ol5yet+2gTfekICS5xS+cYfSIvgn0JksVBVMYVI5QFu/q # hnLhsEFEUzG8fvv0hjgkO+lkpV9ty6GkN4vdnd7ya6Q6aR9y34aiM1qmxaxBi6OU # nyNl6fkuun/diTFnYDLTppOkr/mg5WSfCiDVMNCxtj4wPKC5OmHm1DQIt/MNokbb # H3UGsFP1QbzsLocuSqLCvH09Io3fDPTmscR9Y75G4qX7RTX8AdBPo0I6OEojf39z # uFZt0qOHm65YWQE69cZM2ueE1MB05dNNgHK9gTE7zKvK/fg8B2qjW88MT/WF5V5u # vZGtqa9FSL2RazArA+rDPuf6JGYz4HpgMZHB4S6szWSKYBv0VisCzfxgeU+dquXW # 9bd0auYlOB58DPcOYKdc3Se94g+xL4pcEhbB54JOgAkwYTu/9dLeH2pDqeJZAABV # DWRQCaXfO5LgyKwKCLYXpigrZYCjUSBcr+Ve8PFWMhVTQl0v4q8J/AUmQN5W4n10 # 1cY2L4A7GTQG1h32HHAvfQESWP0xghnlMIIZ4QIBATBuMFcxCzAJBgNVBAYTAlVT # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jv # c29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIdTRnITtcPV0gAAAAAAh0w # DQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYK # KwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFDi+Gr7 # ypR9o07GZrkXXteRwphruk3FX/zEG0ZnubKTMEIGCisGAQQBgjcCAQwxNDAyoBSA # EgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20w # DQYJKoZIhvcNAQEBBQAEggEAdPnCyGTqdb/0vyaZ3csF+KgZd1kuGai5VlQJsQCq # UTc4Z8YdHuHhUWRHwBlUO3pCxNMvQ1pzSYYHtLjkpT5ZkDYG2EGqkdj2fqQ4M1nv # rRgCQ5lBsDSS9Alkg82tHv5KcQbnDSC6hmLxqPKwBlqjCT6m9Hezb7GHRlyKl6DK # 7fPYd5bc1z9/ZE8AfkQfy2zh9by24Lw9oQFKtnHTSTelE348ucbZUAVTexqZgAUK # 66tphmFfsc+av/X+e7C6baS9ernz1gUOgvzvLxfu7zIpI13v2IBV9TLXmqBuG+er # 9WIFTanyWQgdYGPZq1UdsRt7l7FVydXKCJ7eKqsxN0xkTKGCF5cwgheTBgorBgEE # AYI3AwMBMYIXgzCCF38GCSqGSIb3DQEHAqCCF3AwghdsAgEDMQ8wDQYJYIZIAWUD # BAIBBQAwggFSBgsqhkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGEWQoD # ATAxMA0GCWCGSAFlAwQCAQUABCBhIUu5N1n8p4SK9oWVgpRPbXoyuSVuBcGPb4UX # JqSOBQIGal9uVPsBGBMyMDI2MDczMTAzMjIxNC42MTNaMASAAgH0oIHRpIHOMIHL # MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk # bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxN # aWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRT # UyBFU046OTYwMC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0 # YW1wIFNlcnZpY2WgghHtMIIHIDCCBQigAwIBAgITMwAAAiY1tD5nQ5P2HwABAAAC # JjANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAe # Fw0yNjAyMTkxOTQwMDJaFw0yNzA1MTcxOTQwMDJaMIHLMQswCQYDVQQGEwJVUzET # MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV # TWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmlj # YSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046OTYwMC0wNUUw # LUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIi # MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC//w+ZZIL5RFFpVI8D3ZyuNu8I # zcAEOD30OLYjh337rXjcrIlOSzpJc4ZeUxEyli6x6F6zm4NR8dbPb9diDp/hOUzH # WGxiA1Z3RXKBb/4F/ojyvN43SEGWqSfVc3I3BlsYT35ecVAJ9kVf90YOv29tFjJB # BZkYvrT/DwwyRLscOyP4p+9/lyJjD+ULs3YXBhVrfZ+MbQB+BYKLqRvBKbj/wR9a # kNrMxQINoGaD5jZO/N/nSsmG2P1zv/cv4gSoMBnWeQIBkjd2I5w1DeXupp2vSiNm # R5sA2ZkBK3yiQWaJvRxODlkfiyHk9Mkk/TrYTjmjPCbhe+uqhHNRy8UlbOvWsCq0 # tRtUykHv39DgqAfJNrE8OSt835rBzDprrcAhwmgfhoVi4AKeqwikY0nUa48K0Qy8 # 0XT4fiEA3ExEZNaRFo9Nq/GwbfgqKqGmc9xhKuRFcjtua4KHZvnAvpWgEFSOCkov # Xs/BcLnkEHM9xZ8iUag5CyhNqXYYE/z0pcXdYaNIkQ68EWmuvLm7g9oofV2vOm5G # VNoghnkWG6nGPo/JwEgmA9oSS0EfvFRMWPA/gpSvF3shArKHnaEpVSSi3DNbyiuY # iEs9Ko0IkZc8xKFeQRaqGRxrB+2r/7B3X81Tps99KhFwg+wD87od22F2MUg1x7tw # t3gaVnFk0IZIwUPCGwIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFF3hn9fYJN2Y/Z9L # VbBPIxAzXHsQMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1Ud # HwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3Js # L01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggr # BgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNv # bS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIw # MTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgw # DgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQA2Ux0tr9sYCjsq0FRy # iVpx15OurNXv6Qk7iX+ArVPlz3w4tqjcTNm1dt3tTua2wJMpJhPH8n7UXhmT98d5 # Du44Ll4adnse4SQfVg3QL6aRkXHnJUn8y9iftB/Py22n9xnwPFfj3QlDOSgLuHle # u97U0iH2ZaluYabWXJihdiYpK8cPHFlqZOAiot0+GD8dP+RMuvpxt/F2LmYelpoZ # wriiFOUmlxEUV7xJHyZZlDquskeyuq01DTv91N4qM8cfPPhl/2pc4HeMf/nd2Hou # ifJbDQFNd4WPhLzn0Sy3u1Zh3+S3tjQdqN+dyw60RaV+RXCoOLgFZ3MAg/GoDl+f # vb5hy/1a71ctX8wEad1Pf6def2pqfl3wFc++hkF8DXXTZofJN4YVaN3InwbAGQDD # kNK4lqecCixxmSKwidPynGeE5OtvNoK1pkLsm/i8F1RjGczZ/kSF2VDkqG866iQ+ # jVbGOQ6Du3eyyFcFKZoDJ4B5mEAS9aT2SKqllLeybOboH6r67siR5B/2Hnu7+KYu # YZy0BEadtA6ngG4cnSR9JsrkhhsKmb11ujqwgJyNx92MsoGGwNgN1aI0QID8CsjC # FwpfmMzlA44xHKYv3hmjxeqBS4uU5rQeiAnVgpJeaVGKm/lzPDtnppGV+7XhRp5b # 1ZxT/Z7Xxc+I7H7/jCtQDZoaZTCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkA # AAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRl # IEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVow # fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl # ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd # TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX # 9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1q # UoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8d # q6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byN # pOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2k # rnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4d # Pf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgS # Uei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8 # QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6Cm # gyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzF # ER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQID # AQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQU # KqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1 # GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0 # bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMA # QTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbL # j+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1p # Y3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0w # Ni0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIz # LmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwU # tj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN # 3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU # 5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5 # KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGy # qVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB6 # 2FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltE # AY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFp # AUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcd # FYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRb # atGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQd # VTNYs6FwZvKhggNQMIICOAIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMxEzAR # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg # T3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjk2MDAtMDVFMC1E # OTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEw # BwYFKw4DAhoDFQCi/fMxFtkqr7XMXdsRyWU0lSKHZ6CBgzCBgKR+MHwxCzAJBgNV # BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m # dCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA7hZxrjAiGA8y # MDI2MDczMTAwNTgyMloYDzIwMjYwODAxMDA1ODIyWjB3MD0GCisGAQQBhFkKBAEx # LzAtMAoCBQDuFnGuAgEAMAoCAQACAgWqAgH/MAcCAQACAhKaMAoCBQDuF8MuAgEA # MDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAI # AgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAMkvKh2sO3hYPqkxT6+LyZkcG/vq # Sffj2HreUay9ErHeTwGSazkpliWDhCjLgsdyNggQYUsbKkoOX3mgJLeW5lmnK7JZ # W71I/Cqix4yGPAHSyIyq8gQzYwOWIXNp1YKPI93dx9LyvYUXdJa+QQAKsXdJt8Yx # dI6I596/foQPqAnT5TIcyoLYIWX4i6rmf4oILEypkIs3rsktbjGSTR2IS9Aw/pZh # qaS21mFNFYVlMjpAn7KjE390d6umnTMXUw2kuyWWr6dnpJ/laJCaWFF53uGDPxG8 # H+pQm7YqEE8Ol0CIQBOvPKdz1AsHyMbfh00zYspiV+wG8SeZF2TmE+i5cf0xggQN # MIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ # MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u # MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAiY1 # tD5nQ5P2HwABAAACJjANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0G # CyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCAPz0dltMEaMH+PKOO0FbA5H0ln # YFz6gjSuko0mEL0FVDCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIMwyXGFn # TNsZRBrs6GN/BbV0okaNP3VBYqLFjUsFnbgqMIGYMIGApH4wfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTACEzMAAAImNbQ+Z0OT9h8AAQAAAiYwIgQgCn7GJnPN # 5SA3bTJJtjToJPJkPhGNhtdzqyxb6R52p7MwDQYJKoZIhvcNAQELBQAEggIAOCzH # 2Vb2mfF23pV5nYUAe1e6nFUEoHZukmTyXF03602ZkR6iLxK5ugYJAnOnsqsKChYo # I5eNkLjx+hv+36Z7zEm2RaguWpIAax82oHL5ZjxWZmyPisxfit17YW7TpUcv3Fo0 # 19oG3u9lNLuK1Qu92fiC5hjRWiUwVIK6/fYCJ+bd0Hc7ys8f/aAXfxoy6DbVOjsH # zoDF/ZqkYk7MYK6qZq1ztFmlRXdAKNC1WT9j9Unsc5SJPm3p9EfELh2p+/8pbNYC # tJglJa9oEyA37udT2IbjdQ8dt77YVdFy/jVt72YlqJCaaUER2vywZnKNaCs1Sx/C # pKOl87hi0NM6yL/qUvEG5HlHvIdbL6J6iTXJs7ld063TNDFgJ2TDWoF8i9Hi7iml # 3zjHvdmzLnlP9+ah/A9B1Etz/+YvzS5ZLFmNMh6UXsdBOntf1cYKboyctACe6Puf # D6zWG/doRrnf/ittSpq5sB4PK+w2i+Kodh5S7ygnahgpjwld4QwTyr47zfAO7Nfi # DARlnCRPxjsNhc+GcxbXudVyw8q07xWNkpXxMPpzL23ZZkPXnYVAAJu8q+bFzQg9 # MbYejhyatb8be18qcJ6CizhF7zrPVkYavpUjN5fefBuBXsXLRdEEgeBfdu+rxQgz # QQRwOI0aOZFRwKaSLfxn6oOKRfX2sMnw8u1rWYI= # SIG # End signature block |