{"id":494,"date":"2026-04-22T07:41:31","date_gmt":"2026-04-22T07:41:31","guid":{"rendered":"https:\/\/12p.no\/wp\/?p=494"},"modified":"2026-04-22T08:11:25","modified_gmt":"2026-04-22T08:11:25","slug":"automating-globalprotect-certificate-renewal-on-a-palo-alto-firewall","status":"publish","type":"post","link":"https:\/\/12p.no\/wp\/?p=494","title":{"rendered":"Automating GlobalProtect Certificate Renewal on a Palo Alto Firewall"},"content":{"rendered":"\n<p class=\"has-text-align-center\"><em>Disclaimer: This text is highly AI generated<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"709\" src=\"https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/fw-admin-1024x709.png\" alt=\"\" class=\"wp-image-505\" srcset=\"https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/fw-admin-1024x709.png 1024w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/fw-admin-300x208.png 300w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/fw-admin-768x532.png 768w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/fw-admin.png 1036w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Keeping SSL\/TLS certificates updated for a GlobalProtect portal is one of those tasks that sounds simple until you account for validation, firewall policy, certificate import, profile updates, and commits. This project automates that entire workflow with a single Python script.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1002\" height=\"507\" src=\"https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/image.png\" alt=\"\" class=\"wp-image-495\" srcset=\"https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/image.png 1002w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/image-300x152.png 300w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/image-768x389.png 768w\" sizes=\"auto, (max-width: 1002px) 100vw, 1002px\" \/><\/figure>\n\n\n\n<p>Get it here: <a href=\"https:\/\/github.com\/skadevare\/PaloAlto-Letsencrypt-Certificate-Auto-Updater\">https:\/\/github.com\/skadevare\/PaloAlto-Letsencrypt-Certificate-Auto-Updater<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Details<\/h2>\n\n\n\n<p>The script is designed for Palo Alto firewalls and handles both automated Let\u2019s Encrypt renewal and manual certificate import. Its main purpose is to keep a GlobalProtect SSL\/TLS Service Profile updated with the correct certificate without requiring repeated manual work every few months.<br>What Problem This Solves<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>A GlobalProtect portal needs a valid public certificate. If that certificate expires, users will see certificate warnings or lose trust in the portal entirely. Renewing the certificate manually every time is tedious and error-prone.<br>This script automates the full lifecycle:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>opening HTTP access temporarily for ACME validation<\/li>\n\n\n\n<li>running Certbot<\/li>\n\n\n\n<li>closing the temporary firewall access<\/li>\n\n\n\n<li>importing the new certificate into PAN-OS<\/li>\n\n\n\n<li>updating the SSL\/TLS Service Profile<\/li>\n\n\n\n<li>committing the configuration<br>It also supports a manual mode for cases where you already have a certificate and private key and only want to push them to the firewall.<br><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How the Automated Mode Works<\/strong><\/h2>\n\n\n\n<p>In normal mode, the script performs the following steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>It connects to the Palo Alto firewall API.<\/li>\n\n\n\n<li>It checks the current state of a predefined NAT rule and an optional predefined security rule.<\/li>\n\n\n\n<li>If those rules are disabled, it enables them.<\/li>\n\n\n\n<li>It commits the firewall configuration so inbound TCP port 80 is reachable.<\/li>\n\n\n\n<li>It runs Certbot in standalone mode.<\/li>\n\n\n\n<li>Certbot temporarily hosts the HTTP-01 validation response on the local machine.<\/li>\n\n\n\n<li>After validation, the script restores the original rule state and commits again.<\/li>\n\n\n\n<li>It builds a temporary PKCS#12 bundle from the certificate and private key.<\/li>\n\n\n\n<li>It uploads that bundle to the firewall.<\/li>\n\n\n\n<li>It updates the configured SSL\/TLS Service Profile to use the matching certificate object.<\/li>\n\n\n\n<li>It commits the change.<br>This gives you a repeatable certificate renewal process with minimal manual intervention.<br><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Why It Uses Existing Firewall Rules<\/strong><br><\/h2>\n\n\n\n<p>The script does not try to create NAT or security rules from scratch. Instead, it toggles rules that already exist on the firewall.<br>That is intentional.<br>NAT and security rules depend on details that are different in every environment, such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>interface names<\/li>\n\n\n\n<li>zones<\/li>\n\n\n\n<li>public IP addresses<\/li>\n\n\n\n<li>translated addresses<\/li>\n\n\n\n<li>existing policy structure<br>Because of that, the safer design is to create the required rules once in PAN-OS, keep them disabled, and let the script enable and disable them only when needed.<br>Security Rule Handling<br>If a security rule is configured, the script handles it just like the NAT rule.<br>That means:<\/li>\n\n\n\n<li>if the security rule is disabled, it gets enabled before Certbot validation<\/li>\n\n\n\n<li>after validation, it is disabled again<\/li>\n\n\n\n<li>if it was already enabled, the script leaves it enabled<br>This makes the workflow cleaner and avoids leaving temporary access open longer than necessary.<br><br><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"220\" src=\"https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/NAT-rule-1024x220.png\" alt=\"\" class=\"wp-image-501\" srcset=\"https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/NAT-rule-1024x220.png 1024w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/NAT-rule-300x64.png 300w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/NAT-rule-768x165.png 768w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/NAT-rule-1536x330.png 1536w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/NAT-rule.png 1870w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"238\" src=\"https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SEC-rule-1024x238.png\" alt=\"\" class=\"wp-image-502\" srcset=\"https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SEC-rule-1024x238.png 1024w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SEC-rule-300x70.png 300w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SEC-rule-768x179.png 768w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SEC-rule-1536x357.png 1536w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SEC-rule.png 1832w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"691\" src=\"https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SSLTLSPROFILE-1024x691.png\" alt=\"\" class=\"wp-image-503\" srcset=\"https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SSLTLSPROFILE-1024x691.png 1024w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SSLTLSPROFILE-300x202.png 300w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SSLTLSPROFILE-768x518.png 768w, https:\/\/12p.no\/wp\/wp-content\/uploads\/2026\/04\/SSLTLSPROFILE.png 1410w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Manual Certificate Import Mode<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>T<em>he script also supports a manual import mode.<\/em><\/strong><br>This is useful when:<\/li>\n\n\n\n<li>you already received a certificate from another source<\/li>\n\n\n\n<li>you want to test certificate import without running Certbot<\/li>\n\n\n\n<li>you want to update the GlobalProtect profile directly from a certificate and key file<br>Example command:<br>python3 renew_globalprotect_cert.py &#8211;manual-cert &#8211;incert \/path\/to\/fullchain.pem &#8211;inkey \/path\/to\/privkey.pem<br>In manual mode, the script:<\/li>\n\n\n\n<li>skips Certbot entirely<\/li>\n\n\n\n<li>does not touch NAT or security rules<\/li>\n\n\n\n<li>builds the PKCS#12 file<\/li>\n\n\n\n<li>uploads it to the firewall<\/li>\n\n\n\n<li>updates the SSL\/TLS profile<\/li>\n\n\n\n<li>commits the change<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">How Certificate Naming Works<\/h2>\n\n\n\n<p>The script derives the PAN-OS certificate object name from the certificate fingerprint.<br>That gives two benefits:<\/p>\n\n\n\n<p>the same local certificate can be reused cleanly<\/p>\n\n\n\n<p>the script can avoid creating unnecessary duplicate certificate objects<br>If the firewall already has the matching certificate object and the SSL\/TLS profile already points to it, the script skips the update.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Scheduling<\/strong><br><\/h2>\n\n\n\n<p>Manual mode works best with real certificate files or proper Let\u2019s Encrypt paths.<\/p>\n\n\n\n<p>The intended use case is periodic execution through systemd, for example every three months.<br>A quarterly timer matches the original renewal idea, but in practice monthly execution is safer for 90-day Let\u2019s Encrypt certificates. Certbot usually does nothing until a renewal is actually needed, so running more often reduces the risk of missing the renewal window.<br>Important Operational Notes<br>A few things matter in production:<\/p>\n\n\n\n<p>The script performs full PAN-OS commits.<\/p>\n\n\n\n<p>If unrelated candidate changes already exist on the firewall, those should be considered before running it.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Final Thoughts<\/strong><\/h2>\n\n\n\n<p>This script turns certificate renewal for a Palo Alto GlobalProtect portal into a predictable workflow instead of a manual maintenance task. It reduces the chance of expired certificates, keeps the firewall changes temporary, and makes it easier to manage both automatic and manual certificate updates from one place.<br>If you manage GlobalProtect in an environment where certificate rotation has been a recurring headache, this kind of automation can remove a lot of unnecessary operational friction<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Disclaimer: This text is highly AI generated Keeping SSL\/TLS certificates updated for a GlobalProtect portal is one of those tasks that sounds simple until you account for validation, firewall policy, certificate import, profile updates, and commits. This project automates that entire workflow with a single Python script. Get it here: https:\/\/github.com\/skadevare\/PaloAlto-Letsencrypt-Certificate-Auto-Updater Details The script is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-494","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/12p.no\/wp\/index.php?rest_route=\/wp\/v2\/posts\/494","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/12p.no\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/12p.no\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/12p.no\/wp\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/12p.no\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=494"}],"version-history":[{"count":8,"href":"https:\/\/12p.no\/wp\/index.php?rest_route=\/wp\/v2\/posts\/494\/revisions"}],"predecessor-version":[{"id":507,"href":"https:\/\/12p.no\/wp\/index.php?rest_route=\/wp\/v2\/posts\/494\/revisions\/507"}],"wp:attachment":[{"href":"https:\/\/12p.no\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=494"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/12p.no\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=494"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/12p.no\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=494"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}