Get an SVID Using the SPIFFE Python Library
Below is an example python script that uses the Python SPIFFE Library. It gets both JWT and x509 SVIDs and returns an HTTP Client that uses the JWT SVID in the Authorization header and the x509 SVID as the client certificate.
from spiffe import X509Source, JwtSource
from cryptography.hazmat.primitives import serialization
import httpx
import secrets
from tempfile import NamedTemporaryFile
def Session(x509_source: X509Source, jwt_source: JwtSource, jwt_audience: str, authZHeader = "Authorization", additionalHeaders = {}) -> httpx.Client:
# Create a temporary password for the private key file
key_pass = secrets.token_hex(16)
# Serialize the public and private keys to PEM bytes
private_bytes = x509_source.svid.private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.BestAvailableEncryption(bytes(key_pass.encode('utf-8')))).decode()
public_bytes = x509_source.svid.leaf.public_bytes(encoding=serialization.Encoding.PEM).decode()
# Store the certificate and keys in a temporarily file.
# Loading from memory is not supported by any HTTP library (without monkey-patching).
# See:
# 1. https://github.com/encode/httpx/issues/2114
# 2. https://github.com/python/cpython/pull/2449#issuecomment-1429164471
cert_file = NamedTemporaryFile(delete=True)
key_file = NamedTemporaryFile(delete=True)
cert_file.write(public_bytes.encode('utf-8')); cert_file.seek(0)
key_file.write(private_bytes.encode('utf-8')); key_file.seek(0)
# Get a JWT token with the provided audience.
jwt_svid = jwt_source.fetch_svid(audience={jwt_audience})
# Configure the client to use the certificate and key, and append the Authorization Headers
headers = { authZHeader: jwt_svid.token }
headers.update(additionalHeaders)
client = httpx.Client(cert=(f"{cert_file.name}", f"{key_file.name}", key_pass), headers=headers)
return client
Session(X509Source(), JwtSource(), AUTHORIZER_DOMAIN)