Collector Token Authentication
Collector token authentication is used to obtain an authentication token from an HTTP-based API.
It works in combination with the HTTP collector and the XML/JSON collector: those collectors reference the resulting token through the ${token:<name>} placeholder when building their data-collection requests.
Examples may reference vendor APIs that have since changed. Check current vendor documentation before adapting any specific block.
The feature is opt-in.
If token-auth-configuration.xml defines no <token-auth> blocks, no runtime behavior changes.
Collector configurations that do not reference ${token:…} are unaffected.
File location
The configuration lives at ${OPENNMS_HOME}/etc/token-auth-configuration.xml.
A default install includes a minimal stub with commented examples.
The schema is at ${OPENNMS_HOME}/share/xsds/token-auth-configuration.xsd.
Validation runs through the standard bin/config-tester flow.
Define a token-auth block
Each authentication endpoint is one <token-auth> block.
The name attribute is the key used in the ${token:<name>} placeholder.
<token-auth-configuration xmlns="http://xmlns.opennms.org/xsd/config/token-auth">
<token-auth name="catalyst-prod">
<url>https://catalyst.example.com/dna/system/api/v1/auth/token</url>
<method>POST</method>
<basic-auth username="${scv:catalyst:username}" password="${scv:catalyst:password}"/>
<token-from jsonpath="Token"/>
<ttl-seconds>3300</ttl-seconds>
</token-auth>
</token-auth-configuration>
A collector configuration that supports request headers can then reference the resulting token:
<request>
<header name="X-Auth-Token" value="${token:catalyst-prod}"/>
</request>
At request build time, Horizon resolves the placeholder by performing the auth call described in the <token-auth> block.
The resulting token is cached and substituted into the header before the data request is sent.
Element reference
| Element / Attribute | Required | Description |
|---|---|---|
|
yes |
Identifier used in |
|
yes |
HTTP or HTTPS URL of the token-auth endpoint. Per-node placeholders are permitted (see Metadata DSL inside token-auth blocks). |
|
no |
One of |
|
no |
Sends an HTTP Basic |
|
no, repeatable |
Adds a request header to the auth call. Common uses include |
|
no |
Body of the auth request. The |
|
yes |
Locates the token in the auth response. See Token extraction modes. |
|
no |
Optional proactive refresh interval. The cache fetches a new token before this elapses. When unset, the token is held until something invalidates it. |
|
no |
Set to |
|
no |
When |
Token extraction modes
The <token-from> element supports three mutually exclusive modes.
Match the mode to the response shape of the auth API in question.
| Attribute | Description |
|---|---|
|
The token is in the JSON response body at the given slash-separated path. |
|
The token is returned in an HTTP response header. The attribute value is the header name, for example |
|
Set to |
Metadata DSL inside token-auth blocks
Field values inside an <token-auth> block are resolved through the metadata DSL before the auth call goes out.
Three scopes are available:
-
${scv:<alias>:<key>}: This scope reads the value from the secure credentials vault. See Secure Credentials Vault. -
${env:<NAME>}: This scope reads a process environment variable. -
${node:<key>},${requisition:<key>}, etc.: These scopes carry the metadata of the node that triggered the auth lookup. The same logical auth can therefore fan out to per-region or per-tenant endpoints, for examplehttps://${node:label}.api.example.com/auth.
The cache key includes a hash of the resolved fields. Requests that resolve to the same URL, credentials, and body share one cached token.
${token:…} placeholders inside a token-auth block aren’t resolved here.
The block’s own URL, credentials, body, and header values pass through the standard metadata DSL (so ${scv:…}, ${node:…}, etc. work), but a ${token:other} reference is unknown to the DSL and resolves to an empty string.
Chain definitions through other mechanisms (e.g., shared SCV entries) rather than through token references.
|
Caching and refresh
Tokens are held in memory only. A restart drops the cache. A configuration reload flushes it explicitly.
The cache refreshes a token when one of the following holds:
-
No entry exists yet for the resolved auth shape.
-
The configured
<ttl-seconds>has elapsed, or the cache’s internal early-refresh window has been reached. The early-refresh window ismax(600 seconds, 5% of TTL)before the configured TTL expires, so the cache never hands back a token that’s within ten minutes of upstream expiry. -
A downstream collector reports a
FAILEDcollection status and the underlying cause is an HTTP 401 or 403 from the data endpoint. The adaptor invalidates the affected entry; the next collection cycle re-acquires.
Invalidation is passive: the failing request itself isn’t retried. The next scheduled cycle picks up a fresh token. For a Minion-served collection, the FAILED status flows back to the core, where the same adaptor invalidates locally, so the next cycle through the same Minion goes out with a fresh token.
A FAILED status that surfaces for non-auth reasons — RPC timeout, broker outage, generic 5xx, transport error — does not invalidate the cached token.
The adaptor only acts when the exception cause chain carries an auth failure: marker emitted by the collector on a 401/403 from the data endpoint.
|
A short <ttl-seconds> is still useful as defense-in-depth for environments where tokens can be revoked out of band, since it bounds the window during which the cache may hold a token the auth server has already invalidated.
|
Reload without restart
A standard daemon-reload event re-reads token-auth-configuration.xml and flushes the cache:
opennms:send-event -p daemonName=TokenAuth uei.opennms.org/internal/reloadDaemonConfig
A successful reload publishes uei.opennms.org/internal/reloadDaemonConfigSuccessful with daemonName=TokenAuth.
Validation errors (duplicate names, malformed URLs, missing <token-from>) cause the reload to fail and publish reloadDaemonConfigFailed with a truncated reason.
The previously-loaded configuration remains in effect until the next successful reload.
Reference from collector configurations
Both the XML and HTTP collectors accept ${token:<name>} in any header value.
-
In
xml-datacollection-config.xml: This collector supports the placeholder inside a<request>/<header>element of an<xml-source>. -
In
http-datacollection-config.xml: The<url>element supports a<headers>block for the same purpose.
The header value is resolved at request build time, alongside any other metadata DSL placeholders.
A header such as X-Tenant: ${node:foreign-source} and Authorization: Bearer ${token:my-auth} can appear on the same request.
HTTPS
Auth URLs may use either http:// or https://.
HTTPS uses the JVM truststore for certificate validation.
The Certificate Authority needs to be added to ${JAVA_HOME}/lib/security/cacerts, or pointed to via javax.net.ssl.trustStore.
Client certificate (mTLS) authentication on the auth call is not currently supported. Auth definitions can only carry credentials through HTTP Basic, the request body, or request headers.
<disable-ssl-verification>true</disable-ssl-verification> is intended for lab use only. This flag bypasses the certificate trust check entirely.
|
Worked example: Catalyst Center
<token-auth-configuration xmlns="http://xmlns.opennms.org/xsd/config/token-auth">
<token-auth name="catalyst">
<url>https://${node:label}.example.com/dna/system/api/v1/auth/token</url>
<method>POST</method>
<basic-auth username="${scv:catalyst:username}" password="${scv:catalyst:password}"/>
<token-from jsonpath="Token"/>
<ttl-seconds>3300</ttl-seconds>
</token-auth>
</token-auth-configuration>
The XML collector then references the resolved token:
<xml-source url="https://{ipaddr}/dna/intent/api/v1/network-device">
<request>
<header name="X-Auth-Token" value="${token:catalyst}"/>
</request>
...
</xml-source>
Worked example: response header
When the auth API returns the token in a response header rather than the body:
<token-auth name="header-style">
<url>https://api.example.com/login</url>
<method>POST</method>
<content type="application/json">{"identity":"${scv:api:user}","password":"${scv:api:password}"}</content>
<token-from header="X-Auth-Token"/>
<ttl-seconds>1800</ttl-seconds>
</token-auth>
Worked example: body-as-token
When the entire response body is the token (some APIs return a JSON-encoded bare string):
<token-auth name="vsphere-session">
<url>https://vcenter.example.com/api/session</url>
<method>POST</method>
<basic-auth username="${scv:vsphere:username}" password="${scv:vsphere:password}"/>
<token-from body-as-token="true"/>
<ttl-seconds>1800</ttl-seconds>
</token-auth>