Search for AWS

Concepts

Search for AWS answers one question well: what is true in my AWS accounts right now, from inside Splunk, without storing anything. This page explains the model so the rest of the documentation makes sense.

Live access, not ingestion

Splunk’s own AWS content works by ingesting: an add-on pulls CloudTrail, CloudWatch, and Config data into an index, and you search the stored copy. That gives you history, retention, and alerting on trends - at the cost of ingest volume and license usage.

Search for AWS works the other way around. When you run a command, it calls the AWS API live and streams the answer straight into your search. Nothing is written to an index. The consequences are worth internalizing:

  • Always current. You see the account as it is at the moment you search, not as it was when a poller last ran.
  • No index storage, no license volume. Results are not indexed, so they take no index space and count against no ingest quota. What does reach the search head’s disk is short-lived: the search job’s own results in its dispatch directory, as for any Splunk search, until the job expires, and the response cache described under Caching.
  • No history of its own. You see the present, plus whatever AWS itself retains - CloudTrail keeps 90 days of management events for LookupEvents, CloudWatch keeps metrics and logs for as long as you configured, Cost Explorer reports by day. For your own retention you still want ingestion; the two are complementary.

How it works

When you run | awsget kind=instances region=us-east-1, the command runs on the search head. It resolves the account’s credential from Splunk’s encrypted credential store, signs a request to the Cloud Control API, and emits one search row per resource. There is nothing to deploy in AWS and nothing to install anywhere else: a search head reaching out to an API, on demand, when someone runs a search.

Because the work happens on the search head, the app installs there only - never on indexers or forwarders. Every request the app makes carries a User-Agent that begins with os_aws_search/<version> (for example os_aws_search/0.9.0 (linux; amd64)), so its calls can be told apart in CloudTrail’s userAgent field whatever credential made them. One thing is outside its reach: | awsget asks the Cloud Control API, and the describe and list calls Cloud Control then makes for you carry Cloud Control’s own agent. The ListResources and GetResource events carry this app’s.

What you can query

Nine search commands cover the APIs that matter day to day. Each is documented in full in the Command reference:

  • | awsget - list or fetch resources of any kind via the Cloud Control API: EC2, S3, Lambda, IAM, RDS, and every other type that has a list handler, including ones AWS adds later.
  • | awslogs - CloudWatch Logs: a raw event tail, newest first, or a Logs Insights query.
  • | awsmetrics - CloudWatch metrics via GetMetricData, including Metrics Insights queries, and the metric catalog via ListMetrics.
  • | awscloudtrail - recent CloudTrail management events, filtered by event name, user, resource, or source.
  • | awscost - Cost Explorer cost and usage, grouped by service, region, or tag.
  • | awsathena - run an Athena query and stream its rows.
  • | awsglue - browse the Glue Data Catalog: databases, tables, partitions.
  • | awstag - find resources by tag via the Resource Groups Tagging API.
  • | awsjson - reformat a JSON field for reading, in dashboards or the search bar.

Everything the app does is a read. Its commands call only describe, list, get, and query APIs, and the IAM policy it needs grants nothing else. | awsathena is the one command that carries a statement of your own: it hands your SQL to Athena as written, so what that SQL may do is decided by the identity’s IAM permissions, not by the app. The documented policy grants no Glue write actions and lets Athena write to its result bucket only, so a statement that changes the catalog or a table’s data is refused by AWS; an identity with broader permissions could run INSERT, CREATE TABLE AS, or DROP. Keep table data out of the result bucket.

Accounts and regions

Register as many accounts as your license allows, then target them with account= and region= on any command:

| awsget kind=buckets account=payments-prod
| awsget kind=instances account=* region=eu-west-1
| awsget kind=instances account=prod region=*

account=* fans out to every registered account in parallel, and every row carries account and region fields so you can tell results apart and aggregate across the estate. region=* means every region in the account’s allowed regions list when one is configured (see Accounts); without a list, it uses the account’s default region and says so in a search warning - the app never quietly pretends one region is all of them.

Account-global services - IAM, S3, Route 53, Cost Explorer - run once per account whatever region= says, so a fan-out cannot multiply a billed Cost Explorer call.

Errors are per target. During a fan-out, an account or region that fails (an expired key, a denied action, an unreachable endpoint) emits a single row with a _target_error field and the search continues against the others, so one bad account never sinks the whole query. An account whose stored secret cannot be read, or whose role cannot be assumed, is skipped with a warning in the search’s messages instead.

Caching

Repeating a search, or opening a dashboard whose panels all fan out, should not hammer the AWS APIs or your bill. Search for AWS keeps a short-lived disk cache on the search head, with a freshness window per command that reflects how fast the data changes and what a call costs:

CommandDefault freshness
awsget, awslogs, awsmetrics, awsathena1 minute
awscloudtrail, awstag, awsglue5 minutes
awscost1 hour (each call is billed)

Override the window per search with cache=: cache=0 bypasses the cache and always calls AWS, cache=5m accepts a result up to five minutes old. Errors are never cached, and a search that was cut short is never cached either. The cache is partitioned by the AWS identity that made the call - the access key, or the role that was assumed - so a result is only ever served to a search running as that same AWS identity. Users on an account’s shared credential share that credential’s cached results, which is the point of the cache; a per-user override’s cache is private to its owner, whatever key or role it names. An account on the instance role is not cached. You can disable the cache, change its default window, or clear it from the Setup page’s Cache tab; a sweep every five minutes removes expired entries.

Access and credentials

Two things gate a search: the run_aws_search capability (can this Splunk user run the commands at all) and the credential each account resolves to (whose AWS permissions the search runs under). Search for AWS supports a shared account credential and per-user credentials, and stamps the Splunk username into assumed-role sessions so CloudTrail attributes activity to the person. This has its own page: Access control.

What Search for AWS is not

  • Not a historical store. You see current state and whatever AWS retains. For long-term retention and trend alerting over AWS data, ingest it; use Search for AWS alongside that for the live picture.
  • Not an indexed data source. It writes nothing to an index, defines no source types, and is not a Common Information Model data source. There is no index= to search - results exist only for the life of your search.
  • Not free of AWS charges. The app charges nothing per request, but Cost Explorer, Logs Insights, Athena, and CloudWatch bill per call, per GB scanned, or per metric. Costs and performance says which commands cost what, and the dashboards are built to keep those calls deliberate.
  • Read-only. It is a window into your accounts, not a control plane.