{"id":666,"date":"2025-12-24T09:19:10","date_gmt":"2025-12-24T08:19:10","guid":{"rendered":"https:\/\/digitalmaterial.ch\/blog\/?p=666"},"modified":"2025-12-24T09:34:07","modified_gmt":"2025-12-24T08:34:07","slug":"prtg-posh-acme-certificate-deployment-and-renewal","status":"publish","type":"post","link":"https:\/\/digitalmaterial.ch\/blog\/prtg-posh-acme-certificate-deployment-and-renewal\/","title":{"rendered":"PRTG &amp; Posh-ACME &#8211; Certificate Deployment and Renewal"},"content":{"rendered":"\n<p>In regard to the upcoming timeline for certificate lifetimes, services like RPTG are getting more labour-intensive if certificates are continued to be manually deployed. To solve this issue, we&#8217;ve created a script which can be run as a scheduled task. This guide is specifically for using Posh-ACME with the Hosttech DNS API. If you&#8217;d like to use another DNS provider, you can adjust the PowerShell scripts which will be used for a scheduled task. <\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Requirements<\/h2>\n\n\n\n<p>The Posh-ACME, Microsoft.PowerShell.SecretStore, Microsoft.PowerShell.SecretManagement PowerShell Module and a custom Plugin is required in our case. The Hosttech.ps1 needs to be placed in <code>C:\\Program Files\\WindowsPowerShell\\Modules\\Posh-ACME\\[CURRENT_VERSION]\\Plugins\\<\/code>. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>Install-Module -Name Posh-ACME, Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore -Scope AllUsers<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #DCDCAA\">Install-Module<\/span><span style=\"color: #D4D4D4\"> -Name Posh-ACME, Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore -Scope AllUsers<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div data-wp-context=\"{ &quot;autoclose&quot;: false, &quot;accordionItems&quot;: [] }\" data-wp-interactive=\"core\/accordion\" role=\"group\" class=\"wp-block-accordion is-layout-flow wp-block-accordion-is-layout-flow\">\n<div data-wp-class--is-open=\"state.isOpen\" data-wp-context=\"{ &quot;id&quot;: &quot;accordion-item-1&quot;, &quot;openByDefault&quot;: false }\" data-wp-init=\"callbacks.initAccordionItems\" data-wp-on-window--hashchange=\"callbacks.hashChange\" class=\"wp-block-accordion-item is-layout-flow wp-block-accordion-item-is-layout-flow\">\n<h3 class=\"wp-block-accordion-heading\"><button aria-expanded=\"false\" aria-controls=\"accordion-item-1-panel\" data-wp-bind--aria-expanded=\"state.isOpen\" data-wp-on--click=\"actions.toggle\" data-wp-on--keydown=\"actions.handleKeyDown\" id=\"accordion-item-1\" class=\"wp-block-accordion-heading__toggle\"><span class=\"wp-block-accordion-heading__toggle-title\">Click to expand custom plugin hosttech.ps1 script<\/span><span class=\"wp-block-accordion-heading__toggle-icon\" aria-hidden=\"true\">+<\/span><\/button><\/h3>\n\n\n\n<div inert aria-labelledby=\"accordion-item-1\" data-wp-bind--inert=\"!state.isOpen\" id=\"accordion-item-1-panel\" role=\"region\" class=\"wp-block-accordion-panel is-layout-flow wp-block-accordion-panel-is-layout-flow\">\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>Function Get-CurrentPluginType { 'dns-01' }\n\nFunction Add-DnsTxt {\n    &#91;CmdletBinding(DefaultParameterSetName = 'Secure')&#93;\n    param(\n        &#91;Parameter(Mandatory, Position = 0)&#93;\n        &#91;string&#93;$RecordName,\n        &#91;Parameter(Mandatory, Position = 1)&#93;\n        &#91;string&#93;$TxtValue,\n        &#91;Parameter(ParameterSetName = 'Secure', Mandatory, Position = 2)&#93;\n        &#91;securestring&#93;$HosttechToken,\n        &#91;Parameter(ParameterSetName = 'DeprecatedInsecure', Mandatory, Position = 2)&#93;\n        &#91;string&#93;$HosttechTokenInsecure,\n        &#91;Parameter(ValueFromRemainingArguments)&#93;\n        $ExtraParams\n    )\n\n    $apiRoot = 'https:\/\/api.ns1.hosttech.eu\/api'\n\n    # un-secure the password so we can add it to the auth header\n    if ('Secure' -eq $PSCmdlet.ParameterSetName) {\n        $HosttechTokenInsecure = &#91;pscredential&#93;::new('a', $HosttechToken).GetNetworkCredential().Password\n    }\n    $restParams = @{\n        Headers     = @{\n            'Authorization' = \"Bearer $HosttechTokenInsecure\"\n            Accept          = 'application\/json'\n        }\n        ContentType = 'application\/json'\n    }\n\n    # Find the zone for the record\n    if (-not ($zone = Find-HosttechZone $RecordName $restParams)) {\n        throw \"Unable to find matching zone for $RecordName\"\n    }\n\n    # Remove the zone name from the record name to get the relative name\n    $recShort = $RecordName -ireplace \"\\.?$(&#91;regex&#93;::Escape($zone.name.TrimEnd('.')))$\", ''\n\n    # Get a list of existing records for this zone\n    try {\n        Write-Verbose \"Searching for existing TXT records\"\n        $recs = Invoke-RestMethod \"$apiRoot\/user\/v1\/zones\/$($zone.id)\/records\" @restParams -EA Stop\n    }\n    catch { throw }\n\n    # Find all TXT records with the same name\n    $existingRecs = $recs.records | Where-Object {\n        $_.type -eq 'TXT' -and\n        $_.name -eq $recShort\n    }\n\n    # Delete all matching TXT records\n    foreach ($oldRec in $existingRecs) {\n        try {\n            Write-Host \"Deleting existing TXT record: $($oldRec.id)\"\n            Invoke-RestMethod \"$apiRoot\/user\/v1\/zones\/$($zone.id)\/records\/$($oldRec.id)\" -Method Delete @restParams -EA Stop\n        } catch {\n            Write-Warning \"Failed to delete TXT record $($oldRec.id): $_\"\n        }\n    }\n\n    # Now create the new TXT record\n    $body = @{\n        type = 'TXT'\n        name = $recShort\n        text = $TxtValue\n        ttl  = 3600\n    }\n    $json = $body | ConvertTo-Json\n    try {\n        $response = Invoke-RestMethod \"$apiRoot\/user\/v1\/zones\/$($zone.id)\/records\" -Method Post -Body $json @restParams -EA Stop\n        Write-Host \"Full API response: $($response | ConvertTo-Json -Depth 10)\"\n        if ($response.data) {\n            Write-Verbose \"Record $RecordName added with value $TxtValue.\"\n        }\n        else {\n            throw \"Record $RecordName with value $TxtValue could not be added.\"\n        }\n    }\n    catch {\n        if ($_.Exception.Response) {\n            $reader = New-Object IO.StreamReader $_.Exception.Response.GetResponseStream()\n            $body = $reader.ReadToEnd()\n            Write-Host \"API error: $body\"\n        }\n        throw\n    }\n}\n\nFunction Remove-DnsTxt {\n    &#91;CmdletBinding(DefaultParameterSetName = 'Secure')&#93;\n    param(\n        &#91;Parameter(Mandatory, Position = 0)&#93;\n        &#91;string&#93;$RecordName,\n        &#91;Parameter(Mandatory, Position = 1)&#93;\n        &#91;string&#93;$TxtValue,\n        &#91;Parameter(ParameterSetName = 'Secure', Mandatory, Position = 2)&#93;\n        &#91;securestring&#93;$HosttechToken,\n        &#91;Parameter(ParameterSetName = 'DeprecatedInsecure', Mandatory, Position = 2)&#93;\n        &#91;string&#93;$HosttechTokenInsecure,\n        &#91;Parameter(ValueFromRemainingArguments)&#93;\n        $ExtraParams\n    )\n\n    $apiRoot = 'https:\/\/api.ns1.hosttech.eu\/api'\n\n    if ('Secure' -eq $PSCmdlet.ParameterSetName) {\n        $HosttechTokenInsecure = &#91;pscredential&#93;::new('a', $HosttechToken).GetNetworkCredential().Password\n    }\n    $restParams = @{\n        Headers     = @{\n            'Authorization' = \"Bearer $HosttechTokenInsecure\"\n            Accept      = 'application\/json'\n        }\n        ContentType = 'application\/json'\n    }\n\n    if (-not ($zone = Find-HosttechZone $RecordName $restParams)) {\n        throw \"Unable to find matching zone for $RecordName\"\n    }\n\n    try {\n        Write-Verbose \"Searching for existing TXT record\"\n        $recs = Invoke-RestMethod \"$apiRoot\/user\/v1\/zones\/$($zone.id)\/records\" @restParams -EA Stop\n    }\n    catch { throw }\n\n    $rec = $recs.records | Where-Object {\n        $_.type -eq 'TXT' -and\n        $_.name -eq ($RecordName -ireplace \"\\.?$(&#91;regex&#93;::Escape($zone.name.TrimEnd('.')))$\", '') -and\n        $_.text -eq $TxtValue\n    }\n\n    if ($rec) {\n        try {\n            $response = Invoke-RestMethod \"$apiRoot\/user\/v1\/zones\/$($zone.id)\/records\/$($rec.id)\" -Method Delete @restParams -EA Stop\n            if ($response.status -eq 'success') {\n                Write-Verbose \"Record $RecordName deleted.\"\n            }\n            else {\n                throw \"Record $RecordName could not be deleted.\"\n            }\n        }\n        catch { throw }\n    }\n    else {\n        Write-Debug \"Could not find record $RecordName to delete. Nothing to do.\"\n    }\n}\n\nfunction Save-DnsTxt {\n    &#91;CmdletBinding()&#93;\n    param(\n        &#91;Parameter(ValueFromRemainingArguments)&#93;\n        $ExtraParams\n    )\n\n}\n\n# Helper Functions\nFunction Find-HosttechZone {\n    &#91;CmdletBinding()&#93;\n    param(\n        &#91;Parameter(Mandatory, Position = 0)&#93;\n        &#91;string&#93;$RecordName,\n        &#91;Parameter(Mandatory, Position = 1)&#93;\n        &#91;hashtable&#93;$RestParameters\n    )\n\n    $apiRoot = 'https:\/\/api.ns1.hosttech.eu\/api'\n\n    if (!$script:HosttechRecordZones) { $script:HosttechRecordZones = @{} }\n\n    if ($script:HosttechRecordZones.ContainsKey($RecordName)) {\n        Write-Debug \"Result from Cache $($script:HosttechRecordZones.$RecordName.name) (ID $($script:HosttechRecordZones.$RecordName.id))\"\n        return $script:HosttechRecordZones.$RecordName\n    }\n\n    # Get all zones once\n    try {\n        $response = Invoke-RestMethod -Uri \"$apiRoot\/user\/v1\/zones\" @RestParameters -EA Stop\n        Write-Host \"$RestParameters\"\n        $zones = $response.data\n    }\n    catch { throw }\n\n    $zoneTest = $RecordName\n    while ($zoneTest.Contains('.')) {\n        Write-Debug \"Checking $zoneTest\"\n        $zone = $zones | Where-Object { $_.name -eq $zoneTest }\n        if ($zone) {\n            Write-Debug \"Zone $zoneTest found. Zone ID is $($zone.id)\"\n            $script:HosttechRecordZones.$RecordName = @{\n                name = $zone.name\n                id   = $zone.id\n            }\n            return $script:HosttechRecordZones.$RecordName\n        }\n        $zoneTest = $zoneTest.Split('.', 2)&#91;1&#93;\n    }\n\n    Write-Debug \"Zone for $RecordName does not exist ...\"\n    return $null\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Get-CurrentPluginType<\/span><span style=\"color: #D4D4D4\"> { <\/span><span style=\"color: #CE9178\">&#39;dns-01&#39;<\/span><span style=\"color: #D4D4D4\"> }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Add-DnsTxt<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #DCDCAA\">CmdletBinding<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">DefaultParameterSetName<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;Secure&#39;<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">param<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$TxtValue<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">ParameterSetName<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;Secure&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">securestring<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$HosttechToken<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">ParameterSetName<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;DeprecatedInsecure&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$HosttechTokenInsecure<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">ValueFromRemainingArguments<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$ExtraParams<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    )<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$apiRoot<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;https:\/\/api.ns1.hosttech.eu\/api&#39;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\"># un-secure the password so we can add it to the auth header<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #CE9178\">&#39;Secure&#39;<\/span><span style=\"color: #D4D4D4\"> -eq <\/span><span style=\"color: #9CDCFE\">$PSCmdlet<\/span><span style=\"color: #DCDCAA\">.ParameterSetName<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$HosttechTokenInsecure<\/span><span style=\"color: #D4D4D4\"> = &#91;<\/span><span style=\"color: #569CD6\">pscredential<\/span><span style=\"color: #D4D4D4\">&#93;::new(<\/span><span style=\"color: #CE9178\">&#39;a&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">$HosttechToken<\/span><span style=\"color: #D4D4D4\">).GetNetworkCredential().Password<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$restParams<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">@<\/span><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Headers<\/span><span style=\"color: #D4D4D4\">     = <\/span><span style=\"color: #569CD6\">@<\/span><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #CE9178\">&#39;Authorization&#39;<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;Bearer <\/span><span style=\"color: #9CDCFE\">$HosttechTokenInsecure<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">Accept<\/span><span style=\"color: #D4D4D4\">          = <\/span><span style=\"color: #CE9178\">&#39;application\/json&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">ContentType<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;application\/json&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\"># Find the zone for the record<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (-not (<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Find-HosttechZone<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$restParams<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Unable to find matching zone for <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\"># Remove the zone name from the record name to get the relative name<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$recShort<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #D4D4D4\"> -ireplace <\/span><span style=\"color: #CE9178\">&quot;\\.?<\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #D4D4D4\">&#91;<\/span><span style=\"color: #569CD6\">regex<\/span><span style=\"color: #D4D4D4\">&#93;::Escape(<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #DCDCAA\">.name.TrimEnd<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39;.&#39;<\/span><span style=\"color: #D4D4D4\">))<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">$&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;&#39;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\"># Get a list of existing records for this zone<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Verbose<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Searching for existing TXT records&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$recs<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Invoke-RestMethod<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #9CDCFE\">$apiRoot<\/span><span style=\"color: #CE9178\">\/user\/v1\/zones\/<\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">\/records&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">@restParams<\/span><span style=\"color: #D4D4D4\"> -EA Stop<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">catch<\/span><span style=\"color: #D4D4D4\"> { <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\"># Find all TXT records with the same name<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$existingRecs<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$recs<\/span><span style=\"color: #DCDCAA\">.records<\/span><span style=\"color: #D4D4D4\"> | <\/span><span style=\"color: #DCDCAA\">Where-Object<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #DCDCAA\">.type<\/span><span style=\"color: #D4D4D4\"> -eq <\/span><span style=\"color: #CE9178\">&#39;TXT&#39;<\/span><span style=\"color: #D4D4D4\"> -and<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #DCDCAA\">.name<\/span><span style=\"color: #D4D4D4\"> -eq <\/span><span style=\"color: #9CDCFE\">$recShort<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\"># Delete all matching TXT records<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">foreach<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$oldRec<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$existingRecs<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Deleting existing TXT record: <\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$oldRec<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">Invoke-RestMethod<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #9CDCFE\">$apiRoot<\/span><span style=\"color: #CE9178\">\/user\/v1\/zones\/<\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">\/records\/<\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$oldRec<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D4D4D4\"> -Method Delete <\/span><span style=\"color: #9CDCFE\">@restParams<\/span><span style=\"color: #D4D4D4\"> -EA Stop<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        } <\/span><span style=\"color: #C586C0\">catch<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">Write-Warning<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Failed to delete TXT record <\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$oldRec<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">: <\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\"># Now create the new TXT record<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$body<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">@<\/span><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">type<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;TXT&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$recShort<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">text<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$TxtValue<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">ttl<\/span><span style=\"color: #D4D4D4\">  = <\/span><span style=\"color: #B5CEA8\">3600<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$json<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$body<\/span><span style=\"color: #D4D4D4\"> | <\/span><span style=\"color: #DCDCAA\">ConvertTo-Json<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$response<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Invoke-RestMethod<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #9CDCFE\">$apiRoot<\/span><span style=\"color: #CE9178\">\/user\/v1\/zones\/<\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">\/records&quot;<\/span><span style=\"color: #D4D4D4\"> -Method Post -Body <\/span><span style=\"color: #9CDCFE\">$json<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">@restParams<\/span><span style=\"color: #D4D4D4\"> -EA Stop<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Full API response: <\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$response<\/span><span style=\"color: #D4D4D4\"> | <\/span><span style=\"color: #DCDCAA\">ConvertTo-Json<\/span><span style=\"color: #D4D4D4\"> -Depth <\/span><span style=\"color: #B5CEA8\">10<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$response<\/span><span style=\"color: #DCDCAA\">.data<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">Write-Verbose<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Record <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #CE9178\"> added with value <\/span><span style=\"color: #9CDCFE\">$TxtValue<\/span><span style=\"color: #CE9178\">.&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">else<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Record <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #CE9178\"> with value <\/span><span style=\"color: #9CDCFE\">$TxtValue<\/span><span style=\"color: #CE9178\"> could not be added.&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">catch<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #DCDCAA\">.Exception.Response<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">$reader<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">New-Object<\/span><span style=\"color: #D4D4D4\"> IO.StreamReader <\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #DCDCAA\">.Exception.Response.GetResponseStream<\/span><span style=\"color: #D4D4D4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">$body<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$reader<\/span><span style=\"color: #DCDCAA\">.ReadToEnd<\/span><span style=\"color: #D4D4D4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;API error: <\/span><span style=\"color: #9CDCFE\">$body<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">throw<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Remove-DnsTxt<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #DCDCAA\">CmdletBinding<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">DefaultParameterSetName<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;Secure&#39;<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">param<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$TxtValue<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">ParameterSetName<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;Secure&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">securestring<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$HosttechToken<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">ParameterSetName<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;DeprecatedInsecure&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$HosttechTokenInsecure<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">ValueFromRemainingArguments<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$ExtraParams<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    )<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$apiRoot<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;https:\/\/api.ns1.hosttech.eu\/api&#39;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #CE9178\">&#39;Secure&#39;<\/span><span style=\"color: #D4D4D4\"> -eq <\/span><span style=\"color: #9CDCFE\">$PSCmdlet<\/span><span style=\"color: #DCDCAA\">.ParameterSetName<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$HosttechTokenInsecure<\/span><span style=\"color: #D4D4D4\"> = &#91;<\/span><span style=\"color: #569CD6\">pscredential<\/span><span style=\"color: #D4D4D4\">&#93;::new(<\/span><span style=\"color: #CE9178\">&#39;a&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">$HosttechToken<\/span><span style=\"color: #D4D4D4\">).GetNetworkCredential().Password<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$restParams<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">@<\/span><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Headers<\/span><span style=\"color: #D4D4D4\">     = <\/span><span style=\"color: #569CD6\">@<\/span><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #CE9178\">&#39;Authorization&#39;<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;Bearer <\/span><span style=\"color: #9CDCFE\">$HosttechTokenInsecure<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">Accept<\/span><span style=\"color: #D4D4D4\">      = <\/span><span style=\"color: #CE9178\">&#39;application\/json&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">ContentType<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;application\/json&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (-not (<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Find-HosttechZone<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$restParams<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Unable to find matching zone for <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Verbose<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Searching for existing TXT record&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$recs<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Invoke-RestMethod<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #9CDCFE\">$apiRoot<\/span><span style=\"color: #CE9178\">\/user\/v1\/zones\/<\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">\/records&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">@restParams<\/span><span style=\"color: #D4D4D4\"> -EA Stop<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">catch<\/span><span style=\"color: #D4D4D4\"> { <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$rec<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$recs<\/span><span style=\"color: #DCDCAA\">.records<\/span><span style=\"color: #D4D4D4\"> | <\/span><span style=\"color: #DCDCAA\">Where-Object<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #DCDCAA\">.type<\/span><span style=\"color: #D4D4D4\"> -eq <\/span><span style=\"color: #CE9178\">&#39;TXT&#39;<\/span><span style=\"color: #D4D4D4\"> -and<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #DCDCAA\">.name<\/span><span style=\"color: #D4D4D4\"> -eq (<\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #D4D4D4\"> -ireplace <\/span><span style=\"color: #CE9178\">&quot;\\.?<\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #D4D4D4\">&#91;<\/span><span style=\"color: #569CD6\">regex<\/span><span style=\"color: #D4D4D4\">&#93;::Escape(<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #DCDCAA\">.name.TrimEnd<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39;.&#39;<\/span><span style=\"color: #D4D4D4\">))<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">$&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;&#39;<\/span><span style=\"color: #D4D4D4\">) -and<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #DCDCAA\">.text<\/span><span style=\"color: #D4D4D4\"> -eq <\/span><span style=\"color: #9CDCFE\">$TxtValue<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$rec<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">$response<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Invoke-RestMethod<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #9CDCFE\">$apiRoot<\/span><span style=\"color: #CE9178\">\/user\/v1\/zones\/<\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">\/records\/<\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$rec<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D4D4D4\"> -Method Delete <\/span><span style=\"color: #9CDCFE\">@restParams<\/span><span style=\"color: #D4D4D4\"> -EA Stop<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$response<\/span><span style=\"color: #DCDCAA\">.status<\/span><span style=\"color: #D4D4D4\"> -eq <\/span><span style=\"color: #CE9178\">&#39;success&#39;<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #DCDCAA\">Write-Verbose<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Record <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #CE9178\"> deleted.&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">else<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Record <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #CE9178\"> could not be deleted.&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">catch<\/span><span style=\"color: #D4D4D4\"> { <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">else<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Debug<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Could not find record <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #CE9178\"> to delete. Nothing to do.&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Save-DnsTxt<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #DCDCAA\">CmdletBinding<\/span><span style=\"color: #D4D4D4\">()&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">param<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">ValueFromRemainingArguments<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$ExtraParams<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    )<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"># Helper Functions<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">Function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Find-HosttechZone<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #DCDCAA\">CmdletBinding<\/span><span style=\"color: #D4D4D4\">()&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">param<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">Position<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">hashtable<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$RestParameters<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    )<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$apiRoot<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;https:\/\/api.ns1.hosttech.eu\/api&#39;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (!<\/span><span style=\"color: #9CDCFE\">$<\/span><span style=\"color: #569CD6\">script<\/span><span style=\"color: #9CDCFE\">:HosttechRecordZones<\/span><span style=\"color: #D4D4D4\">) { <\/span><span style=\"color: #9CDCFE\">$<\/span><span style=\"color: #569CD6\">script<\/span><span style=\"color: #9CDCFE\">:HosttechRecordZones<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">@<\/span><span style=\"color: #D4D4D4\">{} }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$<\/span><span style=\"color: #569CD6\">script<\/span><span style=\"color: #9CDCFE\">:HosttechRecordZones<\/span><span style=\"color: #DCDCAA\">.ContainsKey<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Debug<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Result from Cache <\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$<\/span><span style=\"color: #569CD6\">script<\/span><span style=\"color: #9CDCFE\">:HosttechRecordZones<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #DCDCAA\">.name<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\"> (ID <\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$<\/span><span style=\"color: #569CD6\">script<\/span><span style=\"color: #9CDCFE\">:HosttechRecordZones<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">)&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$<\/span><span style=\"color: #569CD6\">script<\/span><span style=\"color: #9CDCFE\">:HosttechRecordZones<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\"># Get all zones once<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$response<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Invoke-RestMethod<\/span><span style=\"color: #D4D4D4\"> -Uri <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #9CDCFE\">$apiRoot<\/span><span style=\"color: #CE9178\">\/user\/v1\/zones&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">@RestParameters<\/span><span style=\"color: #D4D4D4\"> -EA Stop<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #9CDCFE\">$RestParameters<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$zones<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$response<\/span><span style=\"color: #DCDCAA\">.data<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">catch<\/span><span style=\"color: #D4D4D4\"> { <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$zoneTest<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">while<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$zoneTest<\/span><span style=\"color: #DCDCAA\">.Contains<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39;.&#39;<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Debug<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Checking <\/span><span style=\"color: #9CDCFE\">$zoneTest<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$zones<\/span><span style=\"color: #D4D4D4\"> | <\/span><span style=\"color: #DCDCAA\">Where-Object<\/span><span style=\"color: #D4D4D4\"> { <\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #DCDCAA\">.name<\/span><span style=\"color: #D4D4D4\"> -eq <\/span><span style=\"color: #9CDCFE\">$zoneTest<\/span><span style=\"color: #D4D4D4\"> }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">Write-Debug<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Zone <\/span><span style=\"color: #9CDCFE\">$zoneTest<\/span><span style=\"color: #CE9178\"> found. Zone ID is <\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #DCDCAA\">.id<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">$<\/span><span style=\"color: #569CD6\">script<\/span><span style=\"color: #9CDCFE\">:HosttechRecordZones<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">@<\/span><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #DCDCAA\">.name<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #9CDCFE\">id<\/span><span style=\"color: #D4D4D4\">   = <\/span><span style=\"color: #9CDCFE\">$zone<\/span><span style=\"color: #DCDCAA\">.id<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$<\/span><span style=\"color: #569CD6\">script<\/span><span style=\"color: #9CDCFE\">:HosttechRecordZones<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$zoneTest<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$zoneTest<\/span><span style=\"color: #DCDCAA\">.Split<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39;.&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">)&#91;<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">Write-Debug<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Zone for <\/span><span style=\"color: #9CDCFE\">$RecordName<\/span><span style=\"color: #CE9178\"> does not exist ...&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">$null<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setting up the environment<\/h2>\n\n\n\n<p>Before we configure the scheduled task, we need to set up a couple of things:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>a secret vault for storing the API key<\/li>\n\n\n\n<li>a password for the vault, stored as passwd.xml in appdata<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>$credentialVault = Get-Credential -UserName 'poshacmevault' -Message 'Enter your Vault password'\n$securePasswordPath = Join-Path $env:LOCALAPPDATA 'PoshACME\\passwd.xml'\n$passwordDir = Split-Path $securePasswordPath -Parent\nif (-not (Test-Path $passwordDir)) {\n    New-Item -Path $passwordDir -ItemType Directory -Force\n}\n$credentialVault.Password | Export-Clixml -Path $securePasswordPath\nRegister-SecretVault -Name poshacmevault -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault\n$password = Import-CliXml -Path $securePasswordPath\n$storeConfiguration = @{\n    Authentication  = 'Password'\n    PasswordTimeout = 3600\n    Interaction     = 'None'\n    Password        = $password\n    Confirm         = $false\n}\nSet-SecretStoreConfiguration @storeConfiguration\nUnlock-SecretStore -Password $password\n$apiKey = Read-Host -Prompt 'Enter your API key'\nSet-Secret -Name HosttechToken -Secret $apiKey<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #9CDCFE\">$credentialVault<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Get-Credential<\/span><span style=\"color: #D4D4D4\"> -UserName <\/span><span style=\"color: #CE9178\">&#39;poshacmevault&#39;<\/span><span style=\"color: #D4D4D4\"> -Message <\/span><span style=\"color: #CE9178\">&#39;Enter your Vault password&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">$securePasswordPath<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Join-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$env:LOCALAPPDATA<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;PoshACME\\passwd.xml&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">$passwordDir<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Split-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$securePasswordPath<\/span><span style=\"color: #D4D4D4\"> -Parent<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (-not (<\/span><span style=\"color: #DCDCAA\">Test-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$passwordDir<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">New-Item<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$passwordDir<\/span><span style=\"color: #D4D4D4\"> -ItemType Directory -Force<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">$credentialVault<\/span><span style=\"color: #DCDCAA\">.Password<\/span><span style=\"color: #D4D4D4\"> | <\/span><span style=\"color: #DCDCAA\">Export-Clixml<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$securePasswordPath<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">Register-SecretVault<\/span><span style=\"color: #D4D4D4\"> -Name poshacmevault -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">$password<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Import-CliXml<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$securePasswordPath<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">$storeConfiguration<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">@<\/span><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">Authentication<\/span><span style=\"color: #D4D4D4\">  = <\/span><span style=\"color: #CE9178\">&#39;Password&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">PasswordTimeout<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">3600<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">Interaction<\/span><span style=\"color: #D4D4D4\">     = <\/span><span style=\"color: #CE9178\">&#39;None&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">Password<\/span><span style=\"color: #D4D4D4\">        = <\/span><span style=\"color: #9CDCFE\">$password<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">Confirm<\/span><span style=\"color: #D4D4D4\">         = <\/span><span style=\"color: #569CD6\">$false<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">Set-SecretStoreConfiguration<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">@storeConfiguration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">Unlock-SecretStore<\/span><span style=\"color: #D4D4D4\"> -Password <\/span><span style=\"color: #9CDCFE\">$password<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">$apiKey<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Read-Host<\/span><span style=\"color: #D4D4D4\"> -Prompt <\/span><span style=\"color: #CE9178\">&#39;Enter your API key&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">Set-Secret<\/span><span style=\"color: #D4D4D4\"> -Name HosttechToken -Secret <\/span><span style=\"color: #9CDCFE\">$apiKey<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Automate with scheduled tasks<\/h2>\n\n\n\n<p>Save the script to a path of your liking. Be sure to adjust the transcript path.<\/p>\n\n\n\n<div data-wp-context=\"{ &quot;autoclose&quot;: false, &quot;accordionItems&quot;: [] }\" data-wp-interactive=\"core\/accordion\" role=\"group\" class=\"wp-block-accordion is-layout-flow wp-block-accordion-is-layout-flow\">\n<div data-wp-class--is-open=\"state.isOpen\" data-wp-context=\"{ &quot;id&quot;: &quot;accordion-item-2&quot;, &quot;openByDefault&quot;: false }\" data-wp-init=\"callbacks.initAccordionItems\" data-wp-on-window--hashchange=\"callbacks.hashChange\" class=\"wp-block-accordion-item is-layout-flow wp-block-accordion-item-is-layout-flow\">\n<h3 class=\"wp-block-accordion-heading\"><button aria-expanded=\"false\" aria-controls=\"accordion-item-2-panel\" data-wp-bind--aria-expanded=\"state.isOpen\" data-wp-on--click=\"actions.toggle\" data-wp-on--keydown=\"actions.handleKeyDown\" id=\"accordion-item-2\" class=\"wp-block-accordion-heading__toggle\"><span class=\"wp-block-accordion-heading__toggle-title\">Click to expand the prtgacmebot.ps1 script<\/span><span class=\"wp-block-accordion-heading__toggle-icon\" aria-hidden=\"true\">+<\/span><\/button><\/h3>\n\n\n\n<div inert aria-labelledby=\"accordion-item-2\" data-wp-bind--inert=\"!state.isOpen\" id=\"accordion-item-2-panel\" role=\"region\" class=\"wp-block-accordion-panel is-layout-flow wp-block-accordion-panel-is-layout-flow\">\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>&lt;#\n    .SYNOPSIS\n    Script to create or renew a certificate using Posh-ACME with Custom Hosttech plugin. Specifically designed for PRTG Network Monitor.\n\n    .DESC(RIPTION\n    This script checks if a certificate exists for the specified domain. If it does not exist, it creates a new certificate.\n\n    .PARAMETER CertName\n        The name of the certificate to create or renew. (e.g., 'prtg.mydomain.com') (required)\n\n    .PARAMETER ContactEmail\n        The email address to use for the certificate. (required)\n\n    .PARAMETER CertLifetime\n        The lifetime of the certificate in days. (optional not yet implemented by Let's Encrypt. Default is 90 days)\n\n    .PARAMETER DaysBeforeExpiration\n        The number of days before expiration to trigger a renewal. (required)\n\n    .PARAMETER ForceRenew\n        Force renewal of the certificate even if it hasn't reached the renewal window. (optional)\n\n    .PARAMETER ExportPath\n        The path where the certificate files will be exported. Default is 'C:\\Program Files (x86)\\PRTG Network Monitor\\cert'. (optional)\n\n    .EXAMPLE\n    .\\prtgacme.ps1 -CertName 'prtg.mydomain.com' -ContactEmail 'hello@mydomain.ch' -DayBeforeExpiration 7 -ExportPath 'C:\\Program Files (x86)\\PRTG Network Monitor\\cert'\n#>\n\nparam(\n    &#91;Parameter(Mandatory = $true)&#93;\n    &#91;string&#93;$CertName,\n\n    &#91;Parameter(Mandatory = $true)&#93;\n    &#91;string&#93;$ContactEmail,\n\n    &#91;Parameter(Mandatory = $true)&#93;\n    &#91;string&#93;$DaysBeforeExpiration,\n\n    &#91;Parameter(Mandatory = $false)&#93;\n    &#91;string&#93;$CertLifetime,\n\n    &#91;Parameter(Mandatory = $false)&#93;\n    &#91;switch&#93;$ForceRenew,\n\n    &#91;Parameter(Mandatory = $false)&#93;\n    &#91;string&#93;$ExportPath = 'C:\\Program Files (x86)\\PRTG Network Monitor\\cert'\n)\n\nStart-Transcript -Path \"C:\\_admin\\prtgacmelog.txt\"\n\nfunction Export-CertificateFiles {\n    param(\n        &#91;Parameter(Mandatory = $true)&#93;\n        &#91;string&#93;$CertName,\n\n        &#91;Parameter(Mandatory = $true)&#93;\n        &#91;string&#93;$ExportPath\n    )\n\n    $certificate = Get-PACertificate -Name $CertName\n    if (-not $certificate) {\n        Write-Error \"Certificate for $CertName not found in Posh-ACME\"\n        return\n    }\n\n    if (-not (Test-Path $ExportPath)) {\n        New-Item -Path $ExportPath -ItemType Directory | Out-Null\n    }\n\n    $targetCrtPath = Join-Path $ExportPath 'prtg.crt'\n    $targetKeyPath = Join-Path $ExportPath 'prtg.key'\n    $targetPemPath = Join-Path $ExportPath 'root.pem'\n\n    if (Test-Path $certificate.CertFile) {\n        Copy-Item -Path $certificate.CertFile -Destination $targetCrtPath -Force\n        Write-Host \"Copied certificate to $targetCrtPath\"\n\n        $content = Get-Content -Path $targetCrtPath -Raw\n        $content = $content -replace \"(?&lt;!`r)`n\", \"`r`n\"\n        Set-Content -Path $targetCrtPath -Value $content\n    }\n\n    if (Test-Path $certificate.KeyFile) {\n        Copy-Item -Path $certificate.KeyFile -Destination $targetKeyPath -Force\n        Write-Host \"Copied private key to $targetKeyPath\"\n\n        $content = Get-Content -Path $targetKeyPath -Raw\n        $content = $content -replace \"(?&lt;!`r)`n\", \"`r`n\"\n        Set-Content -Path $targetKeyPath -Value $content\n    }\n\n    if (Test-Path $certificate.FullChainFile) {\n        Copy-Item -Path $certificate.FullChainFile -Destination $targetPemPath -Force\n        Write-Host \"Copied full certificate chain to $targetPemPath\"\n\n        $content = Get-Content -Path $targetPemPath -Raw\n        $content = $content -replace \"(?&lt;!`r)`n\", \"`r`n\"\n        Set-Content -Path $targetPemPath -Value $content\n    }\n}\n\nfunction Remove-OldCertificates {\n    param(\n        &#91;Parameter(Mandatory = $true)&#93;\n        &#91;string&#93;$CertName\n    )\n\n    $matchingCerts = @(Get-ChildItem -Path 'Cert:\\LocalMachine\\My' | Where-Object { $_.Subject -like \"*$CertName*\"})\n\n    if ($matchingCerts.Count -gt 1) {\n        $newestCert = $matchingCerts | Sort-Object -Property NotAfter -Descending | Select-Object -First 1\n        $oldCerts = $matchingCerts | Where-Object { $_.Thumbprint -ne $newestCert.Thumbprint }\n\n        foreach ($oldCert in $oldCerts) {\n            Write-Host \"Removing old certificate with thumbprint: $($oldCert.Thumbprint) (expires: $($oldCert.NotAfter))\"\n            Remove-Item -Path \"Cert:\\LocalMachine\\My\\$($oldCert.Thumbprint)\" -Force\n        }\n\n        Write-Host \"Cleanup complete. Kept newest certificate with thumbprint: $($newestCert.Thumbprint) (expires: $($newestCert.NotAfter))\"\n    }\n    elseif ($matchingCerts.Count -eq 1) {\n        Write-Host \"Only one certificate found for $CertName, no cleanup needed.\"\n    }\n    else {\n        Write-Host \"No certificates found for $CertName in the LocalMachine\\My store.\"\n    }\n}\n\nif (-not (Get-PAServer)) {\n    Set-PAServer -DirectoryUrl 'https:\/\/acme-v02.api.letsencrypt.org\/directory'\n}\n\nif (-not (Get-PAAccount)) {\n    New-PAAccount -Contact mailto:$ContactEmail -AcceptTOS\n    Set-PAAccount -Contact mailto:$ContactEmail\n}\n\n$securePasswordPath = Join-Path $env:LOCALAPPDATA 'PoshACME\\passwd.xml'\n$password = Import-CliXml -Path $securePasswordPath\nUnlock-SecretStore -Password $password\n$pArgs = @{ HosttechToken = Get-Secret -Name HosttechToken }\nif (-not (Get-PACertificate -Name $CertName)) {\n    Write-Host \"Creating new certificate for $CertName\"\n    New-PACertificate $CertName -AcceptTOS -Contact $ContactEmail -Plugin Hosttech -PluginArgs $pArgs\n    Install-PACertificate\n    Export-CertificateFiles -CertName $CertName -ExportPath $ExportPath\n}\nelse {\n    $lifetime = Get-PACertificate -Name $CertName\n    $daysUntilExpiration = ($lifetime.NotAfter - (Get-Date)).Days\n    if ($DaysBeforeExpiration -lt $daysUntilExpiration) {\n        Write-Host \"Certificate for $CertName is still valid for $daysUntilExpiration days, no renewal needed.\"\n        exit 0\n    }\n    else {\n        Write-Host \"Certificate for $CertName is expiring soon, trying to renew...\"\n        if ($ForceRenew) {\n            Submit-Renewal -MainDomain $CertName -PluginArgs $pArgs -Force\n        } else {\n            Submit-Renewal -MainDomain $CertName -PluginArgs $pArgs\n        }\n        Install-PACertificate\n        Export-CertificateFiles -CertName $CertName -ExportPath $ExportPath\n\t\tRestart-Service PRTGCoreService\n        Remove-OldCertificates -CertName $CertName\n    }\n}\n\nStop-Transcript\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">&lt;#<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    <\/span><span style=\"color: #6A9955\">.<\/span><span style=\"color: #D4D4D4\">SYNOPSIS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    Script to create or renew a certificate using Posh-ACME with Custom Hosttech plugin. Specifically designed for PRTG Network Monitor.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    .DESC(RIPTION<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    This script checks if a certificate exists for the specified domain. If it does not exist, it creates a new certificate.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    <\/span><span style=\"color: #6A9955\">.<\/span><span style=\"color: #D4D4D4\">PARAMETER<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #D4D4D4\">CertName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">        The name of the certificate to create or renew. (e.g., &#39;prtg.mydomain.com&#39;) (required)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    <\/span><span style=\"color: #6A9955\">.<\/span><span style=\"color: #D4D4D4\">PARAMETER<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #D4D4D4\">ContactEmail<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">        The email address to use for the certificate. (required)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    <\/span><span style=\"color: #6A9955\">.<\/span><span style=\"color: #D4D4D4\">PARAMETER<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #D4D4D4\">CertLifetime<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">        The lifetime of the certificate in days. (optional not yet implemented by Let&#39;s Encrypt. Default is 90 days)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    <\/span><span style=\"color: #6A9955\">.<\/span><span style=\"color: #D4D4D4\">PARAMETER<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #D4D4D4\">DaysBeforeExpiration<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">        The number of days before expiration to trigger a renewal. (required)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    <\/span><span style=\"color: #6A9955\">.<\/span><span style=\"color: #D4D4D4\">PARAMETER<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #D4D4D4\">ForceRenew<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">        Force renewal of the certificate even if it hasn&#39;t reached the renewal window. (optional)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    <\/span><span style=\"color: #6A9955\">.<\/span><span style=\"color: #D4D4D4\">PARAMETER<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #D4D4D4\">ExportPath<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">        The path where the certificate files will be exported. Default is &#39;C:\\Program Files (x86)\\PRTG Network Monitor\\cert&#39;. (optional)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    <\/span><span style=\"color: #6A9955\">.<\/span><span style=\"color: #D4D4D4\">EXAMPLE<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    .\\prtgacme.ps1 -CertName &#39;prtg.mydomain.com&#39; -ContactEmail &#39;hello@mydomain.ch&#39; -DayBeforeExpiration 7 -ExportPath &#39;C:\\Program Files (x86)\\PRTG Network Monitor\\cert&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">#&gt;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">param<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$true<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$true<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$ContactEmail<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$true<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$DaysBeforeExpiration<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$false<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$CertLifetime<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$false<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #569CD6\">switch<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$ForceRenew<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$false<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$ExportPath<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&#39;C:\\Program Files (x86)\\PRTG Network Monitor\\cert&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">Start-Transcript<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #CE9178\">&quot;C:\\_admin\\prtgacmelog.txt&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Export-CertificateFiles<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">param<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$true<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$true<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$ExportPath<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    )<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$certificate<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Get-PACertificate<\/span><span style=\"color: #D4D4D4\"> -Name <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (-not <\/span><span style=\"color: #9CDCFE\">$certificate<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Error<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Certificate for <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #CE9178\"> not found in Posh-ACME&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (-not (<\/span><span style=\"color: #DCDCAA\">Test-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$ExportPath<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">New-Item<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$ExportPath<\/span><span style=\"color: #D4D4D4\"> -ItemType Directory | <\/span><span style=\"color: #DCDCAA\">Out-Null<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$targetCrtPath<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Join-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$ExportPath<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;prtg.crt&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$targetKeyPath<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Join-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$ExportPath<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;prtg.key&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$targetPemPath<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Join-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$ExportPath<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;root.pem&#39;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #DCDCAA\">Test-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$certificate<\/span><span style=\"color: #DCDCAA\">.CertFile<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Copy-Item<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$certificate<\/span><span style=\"color: #DCDCAA\">.CertFile<\/span><span style=\"color: #D4D4D4\"> -Destination <\/span><span style=\"color: #9CDCFE\">$targetCrtPath<\/span><span style=\"color: #D4D4D4\"> -Force<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Copied certificate to <\/span><span style=\"color: #9CDCFE\">$targetCrtPath<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$content<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Get-Content<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$targetCrtPath<\/span><span style=\"color: #D4D4D4\"> -Raw<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$content<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$content<\/span><span style=\"color: #D4D4D4\"> -replace <\/span><span style=\"color: #CE9178\">&quot;(?&lt;!<\/span><span style=\"color: #D7BA7D\">`r<\/span><span style=\"color: #CE9178\">)<\/span><span style=\"color: #D7BA7D\">`n<\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D7BA7D\">`r`n<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Set-Content<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$targetCrtPath<\/span><span style=\"color: #D4D4D4\"> -Value <\/span><span style=\"color: #9CDCFE\">$content<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #DCDCAA\">Test-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$certificate<\/span><span style=\"color: #DCDCAA\">.KeyFile<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Copy-Item<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$certificate<\/span><span style=\"color: #DCDCAA\">.KeyFile<\/span><span style=\"color: #D4D4D4\"> -Destination <\/span><span style=\"color: #9CDCFE\">$targetKeyPath<\/span><span style=\"color: #D4D4D4\"> -Force<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Copied private key to <\/span><span style=\"color: #9CDCFE\">$targetKeyPath<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$content<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Get-Content<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$targetKeyPath<\/span><span style=\"color: #D4D4D4\"> -Raw<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$content<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$content<\/span><span style=\"color: #D4D4D4\"> -replace <\/span><span style=\"color: #CE9178\">&quot;(?&lt;!<\/span><span style=\"color: #D7BA7D\">`r<\/span><span style=\"color: #CE9178\">)<\/span><span style=\"color: #D7BA7D\">`n<\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D7BA7D\">`r`n<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Set-Content<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$targetKeyPath<\/span><span style=\"color: #D4D4D4\"> -Value <\/span><span style=\"color: #9CDCFE\">$content<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #DCDCAA\">Test-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$certificate<\/span><span style=\"color: #DCDCAA\">.FullChainFile<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Copy-Item<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$certificate<\/span><span style=\"color: #DCDCAA\">.FullChainFile<\/span><span style=\"color: #D4D4D4\"> -Destination <\/span><span style=\"color: #9CDCFE\">$targetPemPath<\/span><span style=\"color: #D4D4D4\"> -Force<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Copied full certificate chain to <\/span><span style=\"color: #9CDCFE\">$targetPemPath<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$content<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Get-Content<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$targetPemPath<\/span><span style=\"color: #D4D4D4\"> -Raw<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$content<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$content<\/span><span style=\"color: #D4D4D4\"> -replace <\/span><span style=\"color: #CE9178\">&quot;(?&lt;!<\/span><span style=\"color: #D7BA7D\">`r<\/span><span style=\"color: #CE9178\">)<\/span><span style=\"color: #D7BA7D\">`n<\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D7BA7D\">`r`n<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Set-Content<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$targetPemPath<\/span><span style=\"color: #D4D4D4\"> -Value <\/span><span style=\"color: #9CDCFE\">$content<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">Remove-OldCertificates<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">param<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #DCDCAA\">Parameter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Mandatory<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$true<\/span><span style=\"color: #D4D4D4\">)&#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">&#93;<\/span><span style=\"color: #9CDCFE\">$CertName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    )<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$matchingCerts<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">@<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">Get-ChildItem<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #CE9178\">&#39;Cert:\\LocalMachine\\My&#39;<\/span><span style=\"color: #D4D4D4\"> | <\/span><span style=\"color: #DCDCAA\">Where-Object<\/span><span style=\"color: #D4D4D4\"> { <\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #DCDCAA\">.Subject<\/span><span style=\"color: #D4D4D4\"> -like <\/span><span style=\"color: #CE9178\">&quot;*<\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #CE9178\">*&quot;<\/span><span style=\"color: #D4D4D4\">})<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$matchingCerts<\/span><span style=\"color: #DCDCAA\">.Count<\/span><span style=\"color: #D4D4D4\"> -gt <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$newestCert<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$matchingCerts<\/span><span style=\"color: #D4D4D4\"> | <\/span><span style=\"color: #DCDCAA\">Sort-Object<\/span><span style=\"color: #D4D4D4\"> -Property NotAfter -Descending | <\/span><span style=\"color: #DCDCAA\">Select-Object<\/span><span style=\"color: #D4D4D4\"> -First <\/span><span style=\"color: #B5CEA8\">1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$oldCerts<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$matchingCerts<\/span><span style=\"color: #D4D4D4\"> | <\/span><span style=\"color: #DCDCAA\">Where-Object<\/span><span style=\"color: #D4D4D4\"> { <\/span><span style=\"color: #9CDCFE\">$_<\/span><span style=\"color: #DCDCAA\">.Thumbprint<\/span><span style=\"color: #D4D4D4\"> -ne <\/span><span style=\"color: #9CDCFE\">$newestCert<\/span><span style=\"color: #DCDCAA\">.Thumbprint<\/span><span style=\"color: #D4D4D4\"> }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">foreach<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$oldCert<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$oldCerts<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Removing old certificate with thumbprint: <\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$oldCert<\/span><span style=\"color: #DCDCAA\">.Thumbprint<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\"> (expires: <\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$oldCert<\/span><span style=\"color: #DCDCAA\">.NotAfter<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">)&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">Remove-Item<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #CE9178\">&quot;Cert:\\LocalMachine\\My\\<\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$oldCert<\/span><span style=\"color: #DCDCAA\">.Thumbprint<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D4D4D4\"> -Force<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Cleanup complete. Kept newest certificate with thumbprint: <\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$newestCert<\/span><span style=\"color: #DCDCAA\">.Thumbprint<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\"> (expires: <\/span><span style=\"color: #569CD6\">$(<\/span><span style=\"color: #9CDCFE\">$newestCert<\/span><span style=\"color: #DCDCAA\">.NotAfter<\/span><span style=\"color: #569CD6\">)<\/span><span style=\"color: #CE9178\">)&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">elseif<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$matchingCerts<\/span><span style=\"color: #DCDCAA\">.Count<\/span><span style=\"color: #D4D4D4\"> -eq <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Only one certificate found for <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #CE9178\">, no cleanup needed.&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">else<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;No certificates found for <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #CE9178\"> in the LocalMachine\\My store.&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (-not (<\/span><span style=\"color: #DCDCAA\">Get-PAServer<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">Set-PAServer<\/span><span style=\"color: #D4D4D4\"> -DirectoryUrl <\/span><span style=\"color: #CE9178\">&#39;https:\/\/acme-v02.api.letsencrypt.org\/directory&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (-not (<\/span><span style=\"color: #DCDCAA\">Get-PAAccount<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">New-PAAccount<\/span><span style=\"color: #D4D4D4\"> -Contact mailto:<\/span><span style=\"color: #9CDCFE\">$ContactEmail<\/span><span style=\"color: #D4D4D4\"> -AcceptTOS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">Set-PAAccount<\/span><span style=\"color: #D4D4D4\"> -Contact mailto:<\/span><span style=\"color: #9CDCFE\">$ContactEmail<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">$securePasswordPath<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Join-Path<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$env:LOCALAPPDATA<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;PoshACME\\passwd.xml&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">$password<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Import-CliXml<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #9CDCFE\">$securePasswordPath<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">Unlock-SecretStore<\/span><span style=\"color: #D4D4D4\"> -Password <\/span><span style=\"color: #9CDCFE\">$password<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">$pArgs<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">@<\/span><span style=\"color: #D4D4D4\">{ <\/span><span style=\"color: #9CDCFE\">HosttechToken<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Get-Secret<\/span><span style=\"color: #D4D4D4\"> -Name HosttechToken }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (-not (<\/span><span style=\"color: #DCDCAA\">Get-PACertificate<\/span><span style=\"color: #D4D4D4\"> -Name <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #D4D4D4\">)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Creating new certificate for <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #CE9178\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">New-PACertificate<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #D4D4D4\"> -AcceptTOS -Contact <\/span><span style=\"color: #9CDCFE\">$ContactEmail<\/span><span style=\"color: #D4D4D4\"> -Plugin Hosttech -PluginArgs <\/span><span style=\"color: #9CDCFE\">$pArgs<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">Install-PACertificate<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">Export-CertificateFiles<\/span><span style=\"color: #D4D4D4\"> -CertName <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #D4D4D4\"> -ExportPath <\/span><span style=\"color: #9CDCFE\">$ExportPath<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">else<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$lifetime<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Get-PACertificate<\/span><span style=\"color: #D4D4D4\"> -Name <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$daysUntilExpiration<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #9CDCFE\">$lifetime<\/span><span style=\"color: #DCDCAA\">.NotAfter<\/span><span style=\"color: #D4D4D4\"> - (<\/span><span style=\"color: #DCDCAA\">Get-Date<\/span><span style=\"color: #D4D4D4\">)).Days<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$DaysBeforeExpiration<\/span><span style=\"color: #D4D4D4\"> -lt <\/span><span style=\"color: #9CDCFE\">$daysUntilExpiration<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Certificate for <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #CE9178\"> is still valid for <\/span><span style=\"color: #9CDCFE\">$daysUntilExpiration<\/span><span style=\"color: #CE9178\"> days, no renewal needed.&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">exit<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">else<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Write-Host<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;Certificate for <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #CE9178\"> is expiring soon, trying to renew...&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$ForceRenew<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">Submit-Renewal<\/span><span style=\"color: #D4D4D4\"> -MainDomain <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #D4D4D4\"> -PluginArgs <\/span><span style=\"color: #9CDCFE\">$pArgs<\/span><span style=\"color: #D4D4D4\"> -Force<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        } <\/span><span style=\"color: #C586C0\">else<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">Submit-Renewal<\/span><span style=\"color: #D4D4D4\"> -MainDomain <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #D4D4D4\"> -PluginArgs <\/span><span style=\"color: #9CDCFE\">$pArgs<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Install-PACertificate<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Export-CertificateFiles<\/span><span style=\"color: #D4D4D4\"> -CertName <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><span style=\"color: #D4D4D4\"> -ExportPath <\/span><span style=\"color: #9CDCFE\">$ExportPath<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\t\t<\/span><span style=\"color: #DCDCAA\">Restart-Service<\/span><span style=\"color: #D4D4D4\"> PRTGCoreService<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">Remove-OldCertificates<\/span><span style=\"color: #D4D4D4\"> -CertName <\/span><span style=\"color: #9CDCFE\">$CertName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">Stop-Transcript<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<p>You can test it by running it with it&#8217;s required params, check <code>.\\prtgacmebot.ps1 -?<\/code> for all possible params.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>.\\prtgacmebot.ps1 -CertName prtg.yourdomain.ch -ContactEmail hello@yourdomain.ch -DaysBeforeExpiration 30<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">.\\prtgacmebot.ps1 -CertName prtg.yourdomain.ch -ContactEmail hello<\/span><span style=\"color: #9CDCFE\">@yourdomain<\/span><span style=\"color: #DCDCAA\">.ch<\/span><span style=\"color: #D4D4D4\"> -DaysBeforeExpiration <\/span><span style=\"color: #B5CEA8\">30<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This should create a new certificate in your local computer personal store and generate its derived files prtg.pem, prtg.key in the following path &#171;C:\\Program Files (x86)\\PRTG Network Monitor\\cert&#187;.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"175\" src=\"https:\/\/digitalmaterial.ch\/blog\/wp-content\/uploads\/2025\/12\/image-1024x175.png\" alt=\"\" class=\"wp-image-728\" srcset=\"https:\/\/digitalmaterial.ch\/blog\/wp-content\/uploads\/2025\/12\/image-1024x175.png 1024w, https:\/\/digitalmaterial.ch\/blog\/wp-content\/uploads\/2025\/12\/image-300x51.png 300w, https:\/\/digitalmaterial.ch\/blog\/wp-content\/uploads\/2025\/12\/image-768x131.png 768w, https:\/\/digitalmaterial.ch\/blog\/wp-content\/uploads\/2025\/12\/image.png 1194w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"824\" height=\"421\" src=\"https:\/\/digitalmaterial.ch\/blog\/wp-content\/uploads\/2025\/12\/image-2.png\" alt=\"\" class=\"wp-image-730\" style=\"width:890px;height:auto\" srcset=\"https:\/\/digitalmaterial.ch\/blog\/wp-content\/uploads\/2025\/12\/image-2.png 824w, https:\/\/digitalmaterial.ch\/blog\/wp-content\/uploads\/2025\/12\/image-2-300x153.png 300w, https:\/\/digitalmaterial.ch\/blog\/wp-content\/uploads\/2025\/12\/image-2-768x392.png 768w\" sizes=\"auto, (max-width: 824px) 100vw, 824px\" \/><\/figure>\n\n\n\n<p>Create a new basic task and define how often to run it,  we recommended running it at night since the script restarts the PRTG service upon renewing the certificate.<\/p>\n\n\n\n<p>The action could look like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>program\/script: <code>powershell.exe<\/code><\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Add arguments: <code>.\\prtgacmebot.ps1 -CertName prtg.yourdomain.ch -ContactEmail hello@<code>yourdomain<\/code>.ch -DaysBeforeExpiration 30<\/code><\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Start in: <code>C:\\YourPath<\/code><\/li>\n\n\n\n<li>Run whether user is logged on or not.<\/li>\n<\/ul>\n\n\n\n<p>Run the task and check prtgacmelog.txt if everything worked as expected. The script should do the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Get a new certificate if none has been issued for the domain so far.<\/li>\n\n\n\n<li>Renew the existing certificate if certificate validity in days is below your threshold &#171;DaysBeforeExpiration&#187;.<\/li>\n\n\n\n<li>Export the certificate and create the cert files in the correct format for PRTG.<\/li>\n\n\n\n<li>Restart the PRTGCoreService if a new certificate was installed.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Changing the API key in store<\/h2>\n\n\n\n<p>To change the API key, run the following:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>Unlock-SecretStore -Password (Import-Clixml -Path \"$env:LOCALAPPDATA\\PoshACME\\passwd.xml\")\n$newApiKey = Read-Host -Prompt 'Enter your new API key'\nSet-Secret -Name HosttechToken -Secret $newApiKey<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #DCDCAA\">Unlock-SecretStore<\/span><span style=\"color: #D4D4D4\"> -Password (<\/span><span style=\"color: #DCDCAA\">Import-Clixml<\/span><span style=\"color: #D4D4D4\"> -Path <\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #9CDCFE\">$env:LOCALAPPDATA<\/span><span style=\"color: #CE9178\">\\PoshACME\\passwd.xml&quot;<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">$newApiKey<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">Read-Host<\/span><span style=\"color: #D4D4D4\"> -Prompt <\/span><span style=\"color: #CE9178\">&#39;Enter your new API key&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">Set-Secret<\/span><span style=\"color: #D4D4D4\"> -Name HosttechToken -Secret <\/span><span style=\"color: #9CDCFE\">$newApiKey<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In regard to the upcoming timeline for certificate lifetimes, services like RPTG are getting more labour-intensive if certificates are continued to be manually deployed. To solve this issue, we&#8217;ve created a script which can be run as a scheduled task. This guide is specifically for using Posh-ACME with the Hosttech DNS API. If you&#8217;d like [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":742,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[74,73,76,75,72],"class_list":["post-666","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-allgemein","tag-acme","tag-certificate","tag-encrypt","tag-lets","tag-prtg"],"_links":{"self":[{"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/posts\/666","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/comments?post=666"}],"version-history":[{"count":17,"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/posts\/666\/revisions"}],"predecessor-version":[{"id":743,"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/posts\/666\/revisions\/743"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/media\/742"}],"wp:attachment":[{"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/media?parent=666"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/categories?post=666"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/digitalmaterial.ch\/blog\/wp-json\/wp\/v2\/tags?post=666"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}