Configure Palo Alto Networks GlobalProtect VPN with Smallstep
This guide configures Smallstep to issue client certificates for Palo Alto Networks GlobalProtect on Windows, macOS, and Linux. It then configures PAN-OS to authenticate GlobalProtect users with only those certificates.
Intended audience: enterprise IT administrators
The guide has three parts:
- Client support: which GlobalProtect clients can use Smallstep certificates.
- Smallstep configuration: create a credential and a VPN configuration with the Smallstep API.
- PAN-OS configuration: configure the GlobalProtect portal and gateway for certificate authentication.
Client support
Windows
The GlobalProtect client reads certificates from the Windows certificate store. The Smallstep agent registers the TPM-bound key through a CNG key storage provider.
On Windows, a hardware-attested credential goes into the machine certificate store.
The agent puts the certificate in LocalMachine\My, not in the user store,
because the TPM key uses the machine scope of the Microsoft Platform Crypto Provider.
Look for the certificate in certlm.msc, not certmgr.msc.
The GlobalProtect client searches the machine store by default.
See Configure the portal.
macOS
The GlobalProtect client uses the CryptoTokenKit identity that the Smallstep agent manages. The key is held in the Secure Enclave.
Linux: GlobalProtect client
The GlobalProtect client for Linux cannot use a hardware-attested key.
It accepts only a .p12 or .pfx file on the filesystem, imported with globalprotect import-certificate,
and keeps the key in software memory.
See the GlobalProtect documentation for Linux.
The client has no other key source: it does not support PKCS#11 or p11-kit token URIs, it offers no way to load an OpenSSL engine (it statically links OpenSSL 1.1.1, so OpenSSL 3 providers such as the TPM2 provider do not apply), and it does not use an NSS database.
The official GlobalProtect client for Linux cannot use attestation.
A PKCS#12 file contains the private key, and a TPM key cannot be exported to a file.
A Smallstep credential for this client must therefore use a software key without attestation.
The Smallstep API does not accept HARDWARE_ATTESTED with the PKCS#12 format.
See Linux options.
Linux: OpenConnect client
On Linux, we recommend the OpenConnect VPN client instead of the GlobalProtect client. OpenConnect supports the GlobalProtect protocol. It reads a certificate file and a key file, and it supports TPM 2.0 keys in TSS2 files and PKCS#11 keys.
The Smallstep agent writes the certificate and key files in its state directory. With the standard systemd service, the files are:
- Certificate:
/var/lib/step-agent/certificates/globalprotect/service.crt - Key:
/var/lib/step-agent/certificates/globalprotect/service.key
The directory name globalprotect is the credential slug from Step 1.
The files are owned by the step-agent user, with mode 0640.
To connect, run OpenConnect as root. It needs root access to read the key file, to use the TPM, and to create the tunnel interface.
sudo openconnect --protocol=gp \
-c /var/lib/step-agent/certificates/globalprotect/service.crt \
-k /var/lib/step-agent/certificates/globalprotect/service.key \
<portal-fqdn>
Requirements:
- OpenConnect must support TPM 2.0 keys, because the key file is a TPM 2.0 key in TSS2 format.
Run
openconnect --version; the feature list must includeTPMv2. - The device must have a hardware TPM at
/dev/tpmrm0. OpenConnect cannot use a key from the software TPM (swtpm) that the Smallstep agent can use on devices without a TPM.
This procedure applies when the certificate is the only authentication factor. If the portal also requires SAML or a username and password, OpenConnect may need more configuration.
Smallstep configuration
This part uses Smallstep API version 2026-05-01.
It makes two API requests:
- Create a credential. The credential defines the certificate and the key for Windows, macOS, and Linux.
- Create a VPN configuration. The VPN configuration links the credential to the portal FQDN.
The credential issues X.509 certificates that are valid for 4380 hours (6 months). The key is a hardware-bound key with attestation:
- On macOS, the Secure Enclave holds the key.
- On Windows and Linux, the TPM 2.0 holds the key.
Before you start
You need:
- Registered devices. Install the Smallstep agent on each device, register each device with your Smallstep team, and approve each device in the Smallstep console. Assign a user to each device that must authenticate as a user. The certificate common name is the email of the assigned user.
- Authority UUID. In the Smallstep console, go to Certificate Manager → Authorities. Select the authority that will issue the client certificates, and copy its UUID.
- Portal FQDN. Use the FQDN in the certificate of the GlobalProtect portal, not an IP address. The client compares the server certificate to the name that it connects to.
- API token.
- Sign in to the Smallstep console.
- Go to Settings → API Clients.
- Under API tokens, click Add Token.
- Enter a name, for example
GlobalProtect setup. - Under Scopes, select these two scopes:
post-credentials, in the Credentials group.post-vpn, in the Managed Endpoints group.
- Copy the token and keep it in a secure location.
Step 1: Create the credential
Create the credential with the Create Credential endpoint.
Replace YOUR_API_TOKEN and YOUR_AUTHORITY_UUID with your values.
curl -X POST https://gateway.smallstep.com/api/credentials \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Smallstep-Api-Version: 2026-05-01" \
-d '{
"slug": "globalprotect",
"certificate": {
"type": "X509",
"authorityID": "YOUR_AUTHORITY_UUID",
"duration": "4380h",
"fields": {
"commonName": {
"expression": "[identity, device.serial, \"unknown-device\"].filter(v, v != \"\")[0]"
},
"sans": {
"deviceMetadata": ["Device.Serial", "Device.PermanentIdentifier"]
}
}
},
"key": {
"type": "ECDSA_P256",
"protection": "HARDWARE_ATTESTED"
},
"files": {
"keyFormat": "TSS2"
},
"policy": {
"operatingSystem": ["Windows", "macOS", "Linux"]
}
}'
The response contains an id field. Copy this value for Step 2.
Field notes:
-
fields.commonName.expressionsets the certificate common name to the first non-empty value of:- The email of the device's assigned user.
- The device serial number.
- The static value
unknown-device.
The PAN-OS certificate profile reads the username from the common name, so a device with no assigned user and no serial number authenticates as the user
unknown-device. Change this value if necessary. -
The expression replaces
staticanddeviceMetadatafor this field, so the static fallback must be inside the expression. -
The Smallstep API validates the expression when you create the credential. An invalid expression fails at that point, not when the agent requests a certificate.
-
fields.sansadds the device serial number and the device permanent identifier as subject alternative names. -
key.protectionisHARDWARE_ATTESTED. Each device must have a Secure Enclave (macOS) or a TPM 2.0 (Windows and Linux). If a device has neither, the agent does not create the credential on that device; it does not fall back to a software key. -
On Linux, if the device has no TPM and the
swtpmpackage is installed, the Smallstep agent uses a software TPM. Smallstep then records the device with normal assurance, not high assurance. OpenConnect cannot use a key from this software TPM. -
files.keyFormat: TSS2makes the agent write the Linux TPM key as a TSS2 file (it begins with-----BEGIN TSS2 PRIVATE KEY-----). This is also the Linux default for hardware-attested keys. The agent ignores this value on Windows and macOS. -
On Windows, the agent puts hardware-attested certificates in the machine certificate store (
LocalMachine\My). See Configure the portal. -
Do not set
files.crtFile,files.keyFile, orfiles.rootFile. The credential applies to every operating system, and a Linux path such as/etcis not valid on Windows or macOS. -
policy.operatingSystemlimits the credential to Windows, macOS, and Linux devices. Thepolicyobject is optional.
Linux options
Choose one of these two options for Linux devices.
Option A: OpenConnect with a hardware-attested key (recommended)
Use the credential from Step 1 without changes. On Linux, the agent writes the TPM key to a TSS2 file, and OpenConnect uses this file. See Linux: OpenConnect client.
Option B: Official GlobalProtect client with a software key
This option does not use attestation. The key is a software key in a password-protected PKCS#12 file.
-
In Step 1, remove
"Linux"frompolicy.operatingSystem, so the Step 1 credential applies only to Windows and macOS. -
Create a second credential for Linux, using the same authority as in Step 1. Replace
YOUR_API_TOKENandYOUR_AUTHORITY_UUIDwith your values.curl -X POST https://gateway.smallstep.com/api/credentials \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -H "X-Smallstep-Api-Version: 2026-05-01" \ -d '{ "slug": "globalprotect-linux", "certificate": { "type": "X509", "authorityID": "YOUR_AUTHORITY_UUID", "duration": "4380h", "fields": { "commonName": { "expression": "[identity, device.serial, \"unknown-device\"].filter(v, v != \"\")[0]" }, "sans": { "deviceMetadata": ["Device.Serial", "Device.PermanentIdentifier"] } } }, "key": { "type": "ECDSA_P256", "protection": "NONE" }, "files": { "keyFormat": "PKCS12" }, "policy": { "operatingSystem": ["Linux"] } }'
-
Copy the
idfrom the response. In Step 2, add thisidto thecredentialslist. -
On each Linux device, the agent writes two files, owned by the
step-agentuser with mode0640:- The PKCS#12 file:
/var/lib/step-agent/certificates/globalprotect-linux/service.p12 - The password:
/var/lib/step-agent/certificates/globalprotect-linux/password.txt
- The PKCS#12 file:
-
Copy the PKCS#12 file to a location that your user can read:
sudo install -m 0600 -o "$USER" /var/lib/step-agent/certificates/globalprotect-linux/service.p12 ~/globalprotect.p12
-
Show the password:
sudo cat /var/lib/step-agent/certificates/globalprotect-linux/password.txt
-
Import the PKCS#12 file:
globalprotect import-certificate --location ~/globalprotect.p12 -
At the prompt
Please input passcode:, enter the password from step 6.
Field notes for Option B:
protectionmust beNONE. The API acceptsPKCS12only withNONE.PKCS12is accepted forfiles.keyFormat, though it is not yet listed in the API reference.- If the import fails, use
PKCS12_LEGACY. This format uses older encryption for older PKCS#12 parsers. - The client keeps its own copy of the PKCS#12 file. When the agent renews the certificate, it writes a new PKCS#12 file with a new password, and you must repeat steps 5 to 8.
Step 2: Create the VPN configuration
Create the VPN configuration with the Create VPN endpoint.
Replace YOUR_API_TOKEN, YOUR_PORTAL_FQDN, and CREDENTIAL_ID with your values.
If you use Linux Option B, add the id of the second credential to the credentials list.
curl -X POST https://gateway.smallstep.com/api/protect/vpn \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Smallstep-Api-Version: 2026-05-01" \
-d '{
"name": "GlobalProtect",
"connectionType": "SSL",
"vendor": "F5",
"remoteAddress": "YOUR_PORTAL_FQDN",
"autojoin": true,
"credentials": ["CREDENTIAL_ID"]
}'
Field notes:
- The VPN configuration shows the GlobalProtect VPN and its credential in the Smallstep console. The Smallstep agent does not configure the GlobalProtect client or OpenConnect. On Windows and macOS, the agent puts the certificate in the certificate store, and the GlobalProtect client reads it from there. On Linux, the client reads the files that the agent writes.
vendorhas no Palo Alto value. The permitted values areF5,Cisco, andJuniper. UseF5; the GlobalProtect client does not use this value.
Step 3: Download the CA certificates
The agent gets each client certificate from the intermediate CA of your authority, which chains to the root CA. PAN-OS needs both certificates.
- In the Smallstep console, go to Certificate Manager → Authorities.
- Select the authority from Step 1.
- Download the Root Certificate.
- Download the Intermediate Certificate.
PAN-OS configuration
This part changes a working GlobalProtect portal and gateway to use client certificate authentication (mutual TLS). The menu paths are from PAN-OS 12.1.
You need:
- A GlobalProtect portal and gateway that clients can connect to. The portal must have a server TLS certificate for its FQDN, for example from Let's Encrypt.
- The root and intermediate certificates from Step 3.
- Administrator access to PAN-OS, through the web interface or the XML API.
1. Import the client CA certificates
- Go to Device → Certificate Management → Certificates → Import.
- Import the root certificate as a PEM certificate, with the name
gp-client-root. - Import the intermediate certificate as a PEM certificate, with the name
gp-client-intermediate.
A passphrase is not necessary, because a CA certificate has no private key.
If you use the XML API to upload a server certificate, note that PAN-OS rejects an unencrypted private key. Encrypt the server key with a temporary passphrase before you upload it.
2. Create a certificate profile
The certificate profile connects the client CA certificates to GlobalProtect authentication.
- Go to Device → Certificate Management → Certificate Profile → Add.
- Set Name to
gp-client-cert-profile. - Set Username Field to
Subject→common-name. The credential from Step 1 puts the user email in the common name. For a device without an assigned user, the common name is the device serial number. If the device has neither, the common name isunknown-device. - In CA Certificates, add
gp-client-rootandgp-client-intermediate. - Select the options that block sessions with expired certificates and with unknown certificate status.
- Leave Use CRL and Use OCSP cleared for now. After the VPN works, turn on the revocation check in step 7.
3. Create a placeholder authentication profile
PAN-OS requires an authentication profile on the portal and on the gateway, even when you use only certificates. This profile satisfies that requirement. PAN-OS does not use it for the authentication decision; the certificate profile makes that decision.
- Go to Device → Authentication Profile → Add.
- Set Name to
no-auth. - Set Type to
Local Database. Any type works. - Go to Advanced → Allow List and add
all.
4. Configure the portal
- Go to Network → GlobalProtect → Portals →
<your portal>→ Authentication. - Set SSL/TLS Service Profile to your server certificate profile.
- Set Certificate Profile to
gp-client-cert-profile. - Under Client Authentication, add an entry.
- Set Authentication Profile to
no-auth. - Set Allow Authentication with User Credentials OR Client Certificate to Yes.
This setting name is misleading.
Yes means that credentials or a client certificate is sufficient.
With the certificate profile and the no-auth profile, Yes gives certificate-only authentication.
No means that the user must supply a certificate and credentials:
the certificate check passes, but then the client asks for a password,
which fails against the local database, and the user sees "Invalid username or password".
Windows certificate store. On Windows, the agent puts the certificate in the machine certificate store. The default value of Client Certificate Store Lookup in the portal agent configuration is User and machine, so the client searches the user store first and then the machine store. Keep the default value. If a user-store certificate from the same CA exists, set Client Certificate Store Lookup to Machine, so the client searches only the machine store.
5. Configure the gateway
- Go to Network → GlobalProtect → Gateways →
<your gateway>→ Authentication. - Set SSL/TLS Service Profile to your server certificate profile.
- Set Certificate Profile to
gp-client-cert-profile. - Add a Client Authentication entry with
no-auth. - Set Allow Authentication with User Credentials OR Client Certificate to Yes.
You must configure both the portal and the gateway. The client connects to the portal first to get its configuration, then connects to the gateway to build the tunnel, and the portal and the gateway each do their own certificate check.
6. Commit and test
- Commit the candidate configuration.
- On a client device, confirm that the Smallstep agent issued a certificate:
- On macOS, the certificate is in the Keychain.
- On Windows, it is in the machine certificate store,
LocalMachine\My. Opencertlm.mscto see it. It is not in the user store. - On Linux with Option A, it is at
/var/lib/step-agent/certificates/globalprotect/service.crt. - On Linux with Option B, it is at
/var/lib/step-agent/certificates/globalprotect-linux/service.p12.
- Connect to the portal FQDN:
- On Windows, macOS, and Linux with Option B, use the GlobalProtect client.
- On Linux with Option A, run the OpenConnect command in Linux: OpenConnect client.
Expected result: the GlobalProtect client selects the certificate automatically and builds the tunnel without asking for credentials. If the client asks for a username and password, recheck step 4. That setting is the most frequent cause of this problem.
7. Check certificate revocation
Without a revocation check, a certificate that you revoke in Smallstep keeps working on the VPN until it expires. This step makes the firewall ask Smallstep for the status of each client certificate.
What Smallstep publishes
An authority with active revocation puts two URLs in each certificate that it issues:
- An OCSP responder:
http://ocsp.smallstep.com/<authority-id> - A CRL distribution point:
http://crl.smallstep.com/<authority-id>/<file>.crl
To confirm that your authority does this, inspect a client certificate:
step certificate inspect service.crt | grep -A1 -E "OCSP|CRL Distribution"
If the output is empty, the authority does not have active revocation, and the firewall has nothing to check.
Use OCSP, not the CRL
Do not select Use CRL.
PAN-OS 12.1.5 cannot read the Smallstep CRL and gives every certificate the status unknown.
With Block session if certificate status is unknown selected, the firewall then refuses every client.
The system log shows CRL status unknown: unhandled critical CRL extension: issuingDistributionPoint.
- Go to Device → Certificate Management → Certificate Profile →
gp-client-cert-profile. - Select Use OCSP. Leave Use CRL cleared.
- Keep Block session if certificate status is unknown selected.
- Decide what the firewall does when it cannot reach the OCSP responder.
This is the option Block session if certificate status cannot be retrieved within timeout:
- Selected: the firewall refuses a certificate when it cannot get the status. An outage of the responder, or of the path to it, locks out clients.
- Cleared: the firewall accepts a certificate when it cannot get the status, including a revoked certificate.
- Commit.
The firewall sends the OCSP request, not the client.
By default the request leaves from the management interface,
so that interface needs outbound HTTP (TCP port 80) to ocsp.smallstep.com.
Revoke a certificate and confirm the result
Revoke the certificate in the Smallstep console, or with the API:
curl -X POST https://gateway.smallstep.com/api/certificates/SERIAL_NUMBER/revoke \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "X-Smallstep-Api-Version: 2026-05-01"
SERIAL_NUMBER is the serial number in decimal, as the Smallstep API returns it.
PAN-OS and OpenSSL show the same number in hexadecimal, and the API does not accept that form.
The token needs the revoke-certificate scope.
The Smallstep OCSP responder reports the certificate as revoked within seconds. On the firewall, a refused connection adds this line to the system log (Monitor → Logs → System):
SSLMGR certificate ocsp verification failed. OCSP status revoked: cessationOfOperation
The client is not told the reason. It is asked for a username and a password, and that login cannot succeed.
The firewall caches the status
A revocation does not reach the firewall immediately.
The firewall keeps each OCSP answer until the Next Update time in the answer.
For Smallstep that is 24 hours.
A certificate that the firewall saw as valid keeps working after you revoke it, until the firewall asks again.
To make the firewall ask again now, clear both of its caches from the PAN-OS command line:
debug sslmgr delete ocsp all
debug dataplane reset ssl-decrypt certificate-status
The first command alone is not enough. The firewall also keeps the status in a second cache, and it does not send a new OCSP request until that cache is cleared too.
To see what the firewall holds, and whether it asked the responder:
debug sslmgr view ocsp all
debug sslmgr statistics
When the firewall cannot reach the responder
- A certificate with a cached status keeps working until the cached status expires.
- A certificate with no cached status is refused or accepted according to Block session if certificate status cannot be retrieved within timeout. The option Block session if certificate status is unknown does not apply to this case.
- After five failed requests in a row, the firewall stops asking the responder for one hour,
even if the connection returns sooner.
debug sslmgr view ocsp-host allshows the responder asOFFLINE. To make the firewall ask again, rundebug sslmgr delete ocsp-host all.
Troubleshooting
- PAN-OS GlobalProtect log.
Run
show log globalprotect, or go to Monitor → Logs → GlobalProtect. A successful connection shows these events in order:portal-preloginsuccess,portal-authsuccess,gateway-preloginsuccess,gateway-authsuccess. Ifportal-auth failure auth_method=local-databasefollows a successfulportal-prelogin, the setting in step 4 is incorrect. - macOS client logs.
Look in
~/Library/Logs/PaloAltoNetworks/GlobalProtect/.PanGPS.logis the service log, andPanGPA.logis the user interface log. - Server certificate algorithm. Some GlobalProtect client versions do not accept ECDSA server certificates. If the client aborts the TLS handshake, issue an RSA server certificate for the portal and import it again.
Last updated on October 6, 2026
Introducing
Device Identity
Ensure that only company-owned devices can access your enterprise's most sensitive resources.