spotlight_secret

The spotlight_secret resource, and the secret resource of the API: a workspace's credential that Spotlight puts in a request header or query parameter on requests to the hosts it is bound to. Its value never enters a sandbox.

KindEndpointTerraformAddress
secret/api/resources/workspaces/{workspaceId}/secretsspotlight_secret<name>

See Resource API for the operations, headers and errors every kind shares.

Example

resource "spotlight_secret" "acme_api_key" {
  workspace_id = spotlight_workspace.acme.id
  name         = "ACME_API_KEY"
  bindings = [
    { host = "api.acme.example", prefix = "Bearer " },
  ]
  value_wo         = var.secret_acme_api_key
  value_wo_version = 1
}

resource "spotlight_secret" "maps_key" {
  workspace_id = spotlight_workspace.acme.id
  name         = "MAPS_KEY"
  bindings = [
    { host = "maps.googleapis.com", carrier = "query", name = "key" },
  ]
  value_wo         = var.secret_maps_key
  value_wo_version = 1
}

resource "spotlight_secret" "acme_signing" {
  workspace_id = spotlight_workspace.acme.id
  name         = "ACME_SIGNING"
  source = {
    kind      = "aws-secrets-manager"
    secret_id = "acme/signing"
    field     = "secret"
  }
}

Fields

FieldTypeDefaultDescription
namestringrequiredCapitals, digits and _, starting with a capital, at most 64 characters. Fixed: an update that changes it is refused; Terraform replaces the resource.
source.kindstringbuilt-inbuilt-in or aws-secrets-manager. Where the value lives.
source.secretIdstringnoneFor aws-secrets-manager: the secret's name or ARN, 1 to 2,048 of A-Z a-z 0-9 / _ + = . @ : -.
source.fieldstringnoneFor aws-secrets-manager: one key of the JSON the secret holds. No whitespace, at most 256 characters.
bindingsarray of objects[]The hosts the secret is sent to. At most 32, each host once.
valueWostringnoneWrite-only. The value, for built-in. Not empty, at most 64 KiB.
valueWoVersionintegernoneAt least 0. A change, with a new valueWo, rotates the value.
rotatedAtstringread-onlyWhen the value was last set, as an RFC 3339 time.

In Terraform, value_wo is write-only and needs Terraform 1.11 or later.

Sources

source.kindValue
built-inKept by Spotlight, sealed. valueWo is required on create, whenever valueWoVersion changes, and when a secret moves to built-in from another source.
aws-secrets-managerRead from AWS Secrets Manager when the secret is used. valueWo is refused: cannot be set on a secret read from AWS Secrets Manager.

For a run, a secret from AWS Secrets Manager is read by egress with the host's own AWS identity, among the names SPOTLIGHT_EGRESS_READS allows; see Host settings. For an integration request made by Spotlight, it is read only when the deployment reads from AWS Secrets Manager; otherwise the request fails with Secret <NAME> could not be read. This deployment does not read from AWS Secrets Manager.

Bindings

FieldTypeDefaultDescription
hoststringrequiredOne hostname of at least two labels, lowercased, with no scheme, port or path, as in api.acme.example.
carrierstringheaderheader or query. Where the value is put: a request header or a query parameter.
namestringauthorization for a headerThe header or query parameter the value is put in, at most 128 characters. Spotlight holds a header name in lower case. A query parameter has no default, is made of letters, digits and . _ ~ -, and keeps its case.
prefixstring""Up to 64 printable ASCII characters written before the value, as in Bearer . Allowed for both carriers.

A header may not be host, content-length, content-type, transfer-encoding, connection, upgrade, te or trailer.

MessageCause
is where the secret is worn: header or queryA carrier other than header or query.
is the request header the secret is worn in, as in authorization or x-api-keyA header name that is not a valid header, or one of those above.
is the query parameter the secret is worn in, as in key or api_keyA query parameter without a name, or with other characters.

In Terraform, the provider refuses a query binding without a name at plan time with A query parameter must be named.

A secret is sent only over HTTPS, and only to a hostname equal to a bound host. A request to any other address goes without it. A value of more than one line cannot be sent: Secret <NAME> holds more than one line. It cannot be sent in a request. A call that would send two secrets in the same header or query parameter to one host is refused with 409 and Secrets <A> and <B> are both worn in <slot> toward the same host. A request can carry only one of them., where <slot> is the header's name or ?<parameter>.

In what a host answers to a tool call, including an error that repeats the URL or the key, every spelling of the value Spotlight sent, and of the value without its prefix, is replaced by [secret]. This happens before the answer is recorded in the task's journal or handed to the agent. An error reaching the host says [secret] in the value's place.

In a query parameter

On a request Spotlight makes, such as an integration tool's call, the parameter's first occurrence is set to the prefix and the value. Later occurrences of the parameter are dropped, and a missing parameter is added at the end. The rest of the query is kept as it was, in its order and its encoding. A redirect to another host never carries the value; the parameter reads [secret] there. In a run's sandbox, egress rewrites the query the same way, and only where the request carries the stand-in as that parameter's value.

Where a secret is named

A secret is named as secret.<NAME>.

WhereFieldChecked when written
Integrationwebhook.verify.hmac.secretno
Integrationwebhook.verify.token.secretno
Integrationa request's auth.secretsno
Integrationconnection.manual.secretsno
Harness profilemcpServers[].env valuesyes

A secret that is named but not defined fails where it is used, with Secret <NAME> not found. Please define it first. A webhook whose signing secret is not defined answers a plain 401. See Delivery address. A skill declares the secrets it needs in the secrets of its SKILL.md, by name only.

No expression may read a secret's value. See Evaluation.

Rules

  • Writing a secret needs the manage-secrets permission. See Roles and permissions.
  • A secret still named by an integration or a harness profile cannot be deleted. The delete is refused with 409 and Secret <NAME> is in use. Used by: <names>.
  • No read, list, import, export or configuration change holds the value. A configuration change records the value version and the bound hosts.
  • A secret belongs to the workspace, and every team in it can name it.

On this page