|
| 1 | +[](https://opensource.org/licenses/Apache-2.0) |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +_**This open source project is community-supported.** To report a problem or share an idea, use |
| 6 | +**[Issues](https://github.com/Venafi/vcert-python/issues)**; and if you have a suggestion for fixing the issue, please include those details, too. |
| 7 | +In addition, use **[Pull Requests](https://github.com/Venafi/vcert-python/pulls)** to contribute actual bug fixes or proposed enhancements. |
| 8 | +We welcome and appreciate all contributions. Got questions or want to discuss something with our team? |
| 9 | +**[Join us on Slack](https://join.slack.com/t/venafi-integrations/shared_invite/zt-i8fwc379-kDJlmzU8OiIQOJFSwiA~dg)**!_ |
| 10 | + |
| 11 | +# VCert Python SDK for Palo Alto Networks Next-Gen Trust Security (NGTS) |
| 12 | + |
| 13 | +VCert Python is a library and SDK designed to simplify key generation and certificate |
| 14 | +enrollment. This guide covers using it against **Palo Alto Networks Next-Gen Trust Security |
| 15 | +(NGTS)**, also known as Strata Cloud Manager. |
| 16 | + |
| 17 | +> 📌 **NOTE:** Unlike the [Go VCert](https://github.com/Venafi/vcert) project, vcert-python is |
| 18 | +> **SDK-only** — there is no CLI, playbook, or certificate provisioning. NGTS support in this |
| 19 | +> SDK is **certificate-lifecycle only**: `get_policy`/`set_policy`, SSH, and `get_version` |
| 20 | +> raise `NotImplementedError`. |
| 21 | +
|
| 22 | +## Quick Links |
| 23 | + |
| 24 | +- [Prerequisites](#prerequisites) |
| 25 | +- [Connecting](#connecting) |
| 26 | + - [Connection Parameters](#connection-parameters) |
| 27 | + - [API URL Default and Token URL](#api-url-default-and-token-url) |
| 28 | +- [Zone Format](#zone-format) |
| 29 | +- [Examples](#examples) |
| 30 | + - [Connect with service-account credentials](#connect-with-service-account-credentials) |
| 31 | + - [Connect with a pre-issued access token](#connect-with-a-pre-issued-access-token) |
| 32 | + - [Request and retrieve a certificate](#request-and-retrieve-a-certificate) |
| 33 | + - [Renew a certificate](#renew-a-certificate) |
| 34 | + |
| 35 | +## Prerequisites |
| 36 | + |
| 37 | +1. The Palo Alto Networks NGTS API is reachable from where your code runs. The production |
| 38 | + endpoint is `https://api.strata.paloaltonetworks.com/ngts`. |
| 39 | +2. A Palo Alto Networks NGTS service account has been registered and granted the permissions |
| 40 | + needed for the operations you use. See the |
| 41 | + [Palo Alto Networks service account documentation](https://pan.dev/scm/docs/service-accounts/). |
| 42 | + Minimum permissions per SDK operation: |
| 43 | + |
| 44 | + | SDK operation | Required NGTS permissions | |
| 45 | + |---|---| |
| 46 | + | `request_cert` (enroll) | `ngts.certificate_issuing_template.get`, `ngts.certificate_request.create`, `ngts.certificate_request.get`, `ngts.certificate_content.get` | |
| 47 | + | `retrieve_cert` (pickup) | `ngts.certificate_request.get`, `ngts.certificate.get`, `ngts.edge_encryption_key.get`, `ngts.certificate_content.get` | |
| 48 | + | `renew_cert` | `ngts.certificate.search`, `ngts.certificate_content.get`, `ngts.certificate_request.get`, `ngts.certificate.get`, `ngts.certificate_request.create` | |
| 49 | + | `revoke_cert` | _(see your NGTS CA Account configuration)_ | |
| 50 | + | `retire_cert` | `ngts.certificate.search`, `ngts.certificate_request.get`, `ngts.certificate.retire` | |
| 51 | + |
| 52 | +3. You have **either** an OAuth access token, **or** service-account credentials (Client ID, |
| 53 | + Client Secret, and a TSG ID or scope) the SDK can use to obtain one. |
| 54 | +4. A CA Account and an Issuing Template (CIT) exist and are configured with Recommended |
| 55 | + Settings (OU, O, L, ST, C) and appropriate Issuing Rules. You know the Issuing Template's |
| 56 | + **API alias**. |
| 57 | + |
| 58 | +## Connecting |
| 59 | + |
| 60 | +Use `venafi_connection`. NGTS is selected either explicitly via |
| 61 | +`platform=VenafiPlatform.NGTS`, or automatically when `client_id` and `client_secret` are |
| 62 | +supplied (these are NGTS-specific, so they aren't shadowed by the TPP/Cloud branches). |
| 63 | + |
| 64 | +```python |
| 65 | +from vcert import venafi_connection, VenafiPlatform |
| 66 | + |
| 67 | +# Explicit platform selection (token_url defaults to production; override for non-prod) |
| 68 | +conn = venafi_connection( |
| 69 | + platform=VenafiPlatform.NGTS, |
| 70 | + client_id="<service account client id>", |
| 71 | + client_secret="<service account client secret>", |
| 72 | + tsg_id="<tenant service group id>", |
| 73 | +) |
| 74 | + |
| 75 | +# Auto-detection (client_id + client_secret present) |
| 76 | +conn = venafi_connection( |
| 77 | + client_id="<service account client id>", |
| 78 | + client_secret="<service account client secret>", |
| 79 | + tsg_id="<tenant service group id>", |
| 80 | +) |
| 81 | +``` |
| 82 | + |
| 83 | +### Connection Parameters |
| 84 | + |
| 85 | +| Parameter | Required | Description | |
| 86 | +|---|---|---| |
| 87 | +| `client_id` | yes¹ | Service-account Client ID used to obtain an access token. | |
| 88 | +| `client_secret` | yes¹ | Service-account Client Secret used to obtain an access token. | |
| 89 | +| `tsg_id` | yes² | Tenant Service Group ID. Used to derive the OAuth scope as `tsg_id:<TSG_ID>`. | |
| 90 | +| `scope` | yes² | OAuth scope (e.g. `tsg_id:<TSG_ID>`). Takes precedence over `tsg_id` when supplied. | |
| 91 | +| `access_token` | no¹ | A pre-issued OAuth access token. When supplied, `client_id`/`client_secret` become optional (but are still used to refresh the token if present). | |
| 92 | +| `token_url` | no | OAuth token endpoint. Defaults to the Palo Alto production endpoint (see below); override it for non-production environments. | |
| 93 | +| `url` | no | NGTS API base URL. Defaults to the Palo Alto production endpoint (see below). | |
| 94 | +| `http_request_kwargs` | no | Passed through to `requests` (e.g. a trust bundle via `verify`). | |
| 95 | + |
| 96 | +¹ Provide **either** `access_token`, **or** `client_id` + `client_secret`. |
| 97 | +² Provide **either** `scope`, **or** `tsg_id` (used to derive the scope). |
| 98 | + |
| 99 | +### API URL and Token URL Defaults |
| 100 | + |
| 101 | +Both `url` (API base URL) and `token_url` (OAuth token endpoint) are optional. When omitted |
| 102 | +they default to the published Palo Alto **production** endpoints — supply them only for |
| 103 | +non-production environments: |
| 104 | + |
| 105 | +| Parameter | Default | |
| 106 | +|---|---| |
| 107 | +| `url` | `https://api.strata.paloaltonetworks.com/ngts` | |
| 108 | +| `token_url` | `https://auth.apps.paloaltonetworks.com/auth/v1/oauth2/access_token` | |
| 109 | + |
| 110 | +The production token endpoint is taken from the Palo Alto SASE auth API |
| 111 | +([reference](https://pan.dev/sase/api/auth/post-auth-v-1-oauth-2-access-token/)). |
| 112 | + |
| 113 | +#### Safeguards around `token_url` |
| 114 | + |
| 115 | +`token_url` is the **credential sink** — your service-account `client_id`/`client_secret` are |
| 116 | +exchanged there via HTTP Basic auth — so the SDK guards it without giving up the default: |
| 117 | + |
| 118 | +- **HTTPS is enforced.** An `http://` `token_url` is upgraded to `https://` (with a warning) and |
| 119 | + a scheme-less value is assumed to be `https://`, so credentials never travel in cleartext. |
| 120 | +- **Defaulting is logged.** Omitting `token_url` logs a **WARNING** before falling back to the |
| 121 | + production endpoint. This is intentional: if you target a **non-production** tenant but forget to |
| 122 | + set `token_url`, your non-prod credentials would otherwise be sent to the **production** token |
| 123 | + endpoint silently. Always set `token_url` explicitly for non-production. |
| 124 | +- **Untrusted hosts are flagged.** A `token_url` whose host is outside `.paloaltonetworks.com` |
| 125 | + (which covers both production and the documented dev endpoints) logs a **WARNING**, surfacing a |
| 126 | + typo'd or hostile endpoint that would leak credentials. |
| 127 | + |
| 128 | +The last two **warn rather than block**, so a future legitimate endpoint on another domain still |
| 129 | +works — but you should treat these warnings as a prompt to double-check your configuration. |
| 130 | + |
| 131 | +## Zone Format |
| 132 | + |
| 133 | +For NGTS, the **zone is the Issuing Template (CIT) API alias only**. There is no |
| 134 | +`Application\IssuingTemplate` split as there is for CyberArk Certificate Manager, SaaS — the |
| 135 | +entire string (trimmed) is the template alias, and a backslash is part of the alias, not a |
| 136 | +separator. |
| 137 | + |
| 138 | +```python |
| 139 | +zone = "PublicTrust" # the Issuing Template API alias |
| 140 | +``` |
| 141 | + |
| 142 | +## Examples |
| 143 | + |
| 144 | +For the examples below, assume the Issuing Template has an API alias of `PublicTrust`. |
| 145 | + |
| 146 | +### Connect with service-account credentials |
| 147 | + |
| 148 | +```python |
| 149 | +from vcert import venafi_connection, VenafiPlatform |
| 150 | + |
| 151 | +conn = venafi_connection( |
| 152 | + platform=VenafiPlatform.NGTS, |
| 153 | + token_url="<oauth token endpoint>", |
| 154 | + client_id="<client id>", |
| 155 | + client_secret="<client secret>", |
| 156 | + tsg_id="<tsg id>", |
| 157 | +) |
| 158 | +``` |
| 159 | + |
| 160 | +### Connect with a pre-issued access token |
| 161 | + |
| 162 | +```python |
| 163 | +from vcert import venafi_connection, VenafiPlatform |
| 164 | + |
| 165 | +conn = venafi_connection( |
| 166 | + platform=VenafiPlatform.NGTS, |
| 167 | + access_token="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", |
| 168 | +) |
| 169 | +``` |
| 170 | + |
| 171 | +### Request and retrieve a certificate |
| 172 | + |
| 173 | +```python |
| 174 | +from vcert import CertificateRequest |
| 175 | + |
| 176 | +zone = "PublicTrust" |
| 177 | +request = CertificateRequest(common_name="first-time.venafi.example") |
| 178 | +request.san_dns = ["first-san.venafi.example", "second-san.venafi.example"] |
| 179 | + |
| 180 | +conn.request_cert(request, zone) |
| 181 | +cert = conn.retrieve_cert(request) # polls until the certificate is issued |
| 182 | + |
| 183 | +print(cert.cert) # end-entity certificate (PEM) |
| 184 | +print(cert.chain) # chain certificates (PEM) |
| 185 | +print(request.private_key_pem) |
| 186 | +``` |
| 187 | + |
| 188 | +### Renew a certificate |
| 189 | + |
| 190 | +```python |
| 191 | +from vcert import CertificateRequest |
| 192 | + |
| 193 | +# Renew by the enrollment (pickup) id of the existing certificate |
| 194 | +request = CertificateRequest(cert_id="{7428fac3-d0e8-4679-9f48-d9e867a326ca}") |
| 195 | +conn.renew_cert(request) |
| 196 | +cert = conn.retrieve_cert(request) |
| 197 | +``` |
| 198 | + |
| 199 | +--- |
| 200 | + |
| 201 | +For backend-neutral SDK usage (request/retrieve/renew/revoke data objects, output formats), |
| 202 | +see the main [README](README.md). |
0 commit comments