{
  "schema": "aaes/capability-pack/1",
  "provider": "splunk",
  "version": "1.0.0",
  "description": "Splunk: read saved searches, indexes and search jobs, and run ad-hoc SPL searches within a separately restricted role.",
  "notes": "The endpoint authority 'splunk-instance.invalid:8089' is a reserved non-production placeholder (an RFC 2606 reserved TLD) for the customer's splunkd management endpoint: substitute the real management host and port — Splunk Enterprise defaults to port 8089, Splunk Cloud uses https://<deployment-name>.splunkcloud.com:8089 — in the endpoints, the resource locators and the egress allowlist before enabling; the allowlist matches exactly, so all three must be substituted together, substitution is a required deployment step, and allowlisting the reserved host does not make an unsubstituted pack safe (the reserved name is a deliberate fail-closed default: it resolves nowhere by design, so an unsubstituted pack cannot call anything until the installer binds the real host).\n\nEvery read endpoint here is a COLLECTION read only: single-record reads (GET /services/saved/searches/{name}, GET /services/data/indexes/{name}, GET /services/search/jobs/{search_id}) are not registered. The ad-hoc search capability creates and dispatches a search job that executes the caller-supplied SPL — registered as create and execute at the minimum R2 tier, not as retrieval-only POST. The SPL in the request's search parameter is caller-controlled, so this pack cannot pin what data the job touches or what the SPL does, and the constraint is enforced by the Splunk role behind the token plus deployment policy — exactly like the role's GRANTs and the adapter's allowlist in the postgres pack.\n\nSplunk documents capabilities as additive and command-gated, so a demonstrably constrained role must omit at least: delete_by_keyword (the delete operator), output_file (outputcsv and outputlookup writes to files and lookups), run_collect and run_mcollect (writes to summary and metrics indexes), run_sendalert (alert notification actions), run_custom_command (custom search commands, which can carry their own effects), schedule_search, rtsearch and schedule_rtsearch, and every edit_* capability; the role's index access restrictions bound what data the SPL can read.\n\nRegister it only against a role demonstrated to lack those capabilities; if that boundary cannot be demonstrated, remove the capability — one capability id on an unrestricted endpoint is one permission, and a second id would not create a second one.\n\nDocumented exclusions — this pack does not register: saved search creation, modification, deletion or dispatch (POST/DELETE on saved/searches, which can schedule alerting), index creation or modification (POST data/indexes), search job control (DELETE or control actions on search/jobs), knowledge object writes, HEC event ingest (a separate input, default port 8088, that no capability here may reach), servicesNS user-namespace endpoints, and every other splunkd endpoint — an excluded operation.",
  "credential": {
    "secret_ref_id": "secret-ref-splunk-auth-token",
    "custody": "customer_vault",
    "inject": "header",
    "inject_name": "Authorization",
    "note": "A Splunk platform authentication token (JWT) for the customer's own instance, held in the client's own secret manager. The stored material must be the complete Authorization header value: the scheme 'Bearer', one separating space, then the token — 'Bearer <token>' (Splunk also accepts the 'Splunk' scheme; this pack standardizes on the documented Bearer form). The token authenticates with the full role and capabilities of the Splunk user it was issued to: issue it to a dedicated least-privilege service role whose index restrictions and capabilities cover exactly these reads and, where enabled, ad-hoc search without the destructive, writing or notifying capabilities enumerated in the pack notes (delete_by_keyword, output_file, run_collect, run_mcollect, run_sendalert, run_custom_command, schedule_search).\n\nTokens carry a not-before and an expiry chosen at creation, and Splunk's documentation states expired tokens are unusable — choose a real expiry and rotate; renewal ownership sits with an external deployment process, and the executor injects the stored value verbatim and performs no token lifecycle of its own. Revocation is real but manual: an administrator disabling or deleting the token ends its access, as does disabling token authentication on the instance — do not assume that restricting new token issuance invalidates tokens already issued.\n\nThe full token is shown to the requester once at assignment, so capture it into the vault at creation time.\n\nExecutor hygiene: the value must live only in executor memory for the lifetime of a call, must never be written to logs, traces or diagnostics, and must not appear in crash dumps; a deployment that cannot meet that bar must not enable the pack."
  },
  "capabilities": [
    {
      "capability_id": "splunk.saved_searches.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "splunk-instance.invalid:8089"
      ],
      "endpoint": "https://splunk-instance.invalid:8089/services/saved/searches",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-splunk-auth-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "splunk-deployment",
      "description": "List saved search configurations: names, schedules and the SPL text itself, which reveals detection logic and internal data layout. The registered path covers the collection read only — single saved-search reads, creation, modification, deletion and dispatch are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "splunk.indexes.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "splunk-instance.invalid:8089"
      ],
      "endpoint": "https://splunk-instance.invalid:8089/services/data/indexes",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-splunk-auth-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "splunk-deployment",
      "description": "List data indexes: names, storage paths, sizes, event counts and retention settings, which reveal what the deployment collects and keeps. The registered path covers the collection read only — single-index reads and index creation or modification (POST data/indexes) are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "splunk.search.jobs.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "splunk-instance.invalid:8089"
      ],
      "endpoint": "https://splunk-instance.invalid:8089/services/search/jobs",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-splunk-auth-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "splunk-deployment",
      "description": "List current search jobs: owners, dispatch state, disk usage and the query text of each job, which reveals who searches for what. The registered path covers the collection read only — single-job reads (GET /services/search/jobs/{search_id}), job results and job control are not registered by this pack.",
      "requires_review": true
    },
    {
      "capability_id": "splunk.search.jobs.create",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R2",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "pii",
      "egress_allowlist": [
        "splunk-instance.invalid:8089"
      ],
      "endpoint": "https://splunk-instance.invalid:8089/services/search/jobs",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-splunk-auth-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "create",
        "execute"
      ],
      "resource_id": "splunk-indexed-data",
      "description": "Create and run an ad-hoc search job using caller-supplied SPL in the search parameter. POST /services/search/jobs executes the query; it is registered as create and execute at R2. Reading results through GET /services/search/jobs/{search_id}/results is a separate operation excluded from this package.\n\nThe package does not restrict SPL or the data it can reach. Enforce those limits through the Splunk role behind the token and deployment policy. Before enabling, demonstrate that the role lacks destructive, writing, and notifying capabilities: delete_by_keyword, output_file, run_collect, run_mcollect, run_sendalert, run_custom_command, schedule_search, and edit_*.\n\nThe default data class is pii because indexed events often contain IP addresses, usernames, or email text. Lower it only when the accessible indexes contain no personal data; raise it for regulated data.",
      "requires_review": true
    }
  ],
  "resources": [
    {
      "resource_id": "splunk-deployment",
      "kind": "api",
      "locator": "https://splunk-instance.invalid:8089/services",
      "data_class": "internal",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "splunk-indexed-data",
      "kind": "api",
      "locator": "https://splunk-instance.invalid:8089/services/search/jobs",
      "data_class": "pii",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    }
  ],
  "review": {
    "state": "library",
    "date": "2026-09-22",
    "sources": [
      "https://docs.splunk.com/Documentation/Splunk/latest/RESTREF/RESTsearch (retrieved 2026-09-21)",
      "https://help.splunk.com/en/splunk-enterprise/rest-api-reference/9.4/introspection-endpoints/introspection-endpoint-descriptions (retrieved 2026-09-21)",
      "https://help.splunk.com/en/splunk-enterprise/leverage-rest-apis/rest-api-reference/9.4/introduction/endpoints-reference-list (retrieved 2026-09-21)",
      "https://docs.splunk.com/Documentation/Splunk/latest/Security/UseAuthTokens (retrieved 2026-09-21)",
      "https://docs.splunk.com/Documentation/Splunk/latest/Security/Rolesandcapabilities (retrieved 2026-09-21)"
    ],
    "reviewer_id": "aaes-eng"
  }
}
