Authentication¶
pyfsr supports two authentication methods, selected by the type of the auth
argument you pass to FortiSOAR.
API token¶
Pass the token as a string. This is the recommended method for automation:
from pyfsr import FortiSOAR
client = FortiSOAR("soar.example.com", "your-api-token")
Username & password¶
Pass a (username, password) tuple. pyfsr exchanges these for a session token:
client = FortiSOAR("soar.example.com", ("admin", "password"))
Transport options¶
client = FortiSOAR(
"soar.example.com",
"your-api-token",
verify_ssl=False, # self-signed appliances
suppress_insecure_warnings=True, # silence urllib3 warnings
port=8443, # non-standard port
timeout=60, # per-request timeout (seconds)
max_retries=3, # transient-failure retries
verbose=True, # debug logging (secrets masked)
)
Note
Authorization headers, API keys, cookies, and CSRF tokens are masked in logs
even when verbose=True, so debug output stays safe to share.
Environment-based config¶
For apps and the bundled MCP server, drive configuration from FSR_*
environment variables via EnvConfig instead of hard-wiring
host and credentials:
from pyfsr import EnvConfig
client = EnvConfig.from_env().client()
from_env reads FSR_* from the environment (or a dict you pass) and resolves
a plain config object — no network, so the resolved shape is safe to doctest:
>>> from pyfsr import EnvConfig
>>> cfg = EnvConfig.from_env({
... "FSR_BASE_URL": "https://soar.example.com",
... "FSR_API_KEY": "key-123",
... })
>>> cfg.base_url, cfg.auth, cfg.verify_ssl, cfg.timeout
('https://soar.example.com', 'key-123', True, 30)
>>> type(cfg.auth).__name__ # a lone key resolves to a str
'str'
>>> user_pw = EnvConfig.from_env({
... "FSR_BASE_URL": "https://soar.example.com",
... "FSR_USERNAME": "admin", "FSR_PASSWORD": "secret",
... })
>>> type(user_pw.auth).__name__ # user+password resolves to a tuple
'tuple'
When required variables are missing it raises ValueError with an actionable
message — pass an explicit env dict to make the failure deterministic:
>>> try:
... EnvConfig.from_env({}) # no host
... except ValueError as e:
... str(e)
'missing required configuration: FSR_BASE_URL (or FSR_HOST); FSR_API_KEY, or both FSR_USERNAME and FSR_PASSWORD'
>>> try:
... EnvConfig.from_env({"FSR_BASE_URL": "https://soar.example.com"}) # no auth
... except ValueError as e:
... str(e)
'missing required configuration: FSR_API_KEY, or both FSR_USERNAME and FSR_PASSWORD'
Variable |
Purpose |
|---|---|
|
Appliance host or URL (required; |
|
API-key auth |
|
Username/password auth (alternative to |
|
Optional port override |
|
|
|
Silence urllib3 warnings when SSL is off |
|
Per-request timeout in seconds (default 30) |
Note
EnvConfig.from_env() itself never touches the network — it only resolves
config. The live validation call happens later, inside
FortiSOAR, when you call .client() (or
construct FortiSOAR(...) directly): constructing the client validates the
credential against the appliance.