You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add write-only headers and request bodies (Closes#115, #116)
Introduce headers_wo and request_body_wo on terracurl_request with version
attributes, private-state snapshots for read/destroy, and Terraform 1.11+ support.
Co-authored-by: Cursor <cursoragent@cursor.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,3 +1,9 @@
1
+
## 2.8.0
2
+
3
+
ENHANCEMENTS:
4
+
5
+
- Add write-only headers and request bodies on `terracurl_request` resources with `_wo_version` companions and private-state snapshots for read/destroy. Requires Terraform 1.11+. Closes #115, #116.
Copy file name to clipboardExpand all lines: docs/guides/default_headers.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -80,7 +80,7 @@ Provider headers win on key collision. This ensures a fresh provider token repla
80
80
## Limitations
81
81
82
82
- Tokens set only in resource `headers` or `destroy_headers` are still persisted in state. For destroy-only refresh, move auth to `default_headers` or run `terraform apply` before destroy to update state.
83
-
- Write-only resource headers (see issue #115) are a separate follow-up to avoid persisting secrets in state entirely.
83
+
- Write-only resource headers (see the [Write-Only Headers and Request Bodies guide](write_only)) avoid persisting secrets in state entirely.
84
84
-`default_headers` is marked sensitive in the provider schema and will not appear in plan output.
Copy file name to clipboardExpand all lines: docs/guides/digest_auth.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -87,7 +87,7 @@ If credentials are set only in `destroy_digest_auth`, those values are persisted
87
87
88
88
- HTTP Basic authentication is not built in; set a static `Authorization: Basic ...` header manually or use provider `default_headers`.
89
89
- NTLM, Kerberos, and other enterprise proxy authentication mechanisms remain unsupported. See the [HTTP Proxy Support guide](proxy).
90
-
- Digest credentials configured on resources are stored in Terraform state (marked sensitive). Write-only credentials are tracked separately in issue #115.
90
+
- Digest credentials configured on resources are stored in Terraform state (marked sensitive). For credentials that must not appear in state, use write-only headers or provider `default_headers` where applicable. See the [Write-Only Headers and Request Bodies guide](write_only).
91
91
- Custom `realm` or algorithm tuning is not exposed unless a real API requires it.
page_title: "Write-Only Headers and Request Bodies"
3
+
subcategory: "Guides"
4
+
description: |-
5
+
Use write-only headers and request bodies on terracurl_request resources to send secrets without persisting them in Terraform state.
6
+
---
7
+
8
+
# Write-Only Headers and Request Bodies
9
+
10
+
Terraform 1.11+ supports **write-only arguments**: values supplied in configuration that are used during apply but are **not stored in plan or state JSON**. TerraCurl exposes this for `terracurl_request` resource headers and request bodies on create, read, and destroy operations.
11
+
12
+
Use write-only attributes when secrets must not appear in `terraform show`, remote state, or version control–backed state files — even when marked `sensitive`.
13
+
14
+
## Requirements
15
+
16
+
- Terraform **1.11 or later**
17
+
-`terracurl_request`**resource only** (write-only is not available on data sources, actions, or ephemeral resources)
18
+
19
+
## Create example
20
+
21
+
```terraform
22
+
resource "terracurl_request" "example" {
23
+
name = "example"
24
+
url = "https://api.example.com/resource"
25
+
method = "PUT"
26
+
27
+
headers_wo = {
28
+
X-Vault-Token = var.vault_token
29
+
}
30
+
headers_wo_version = 1
31
+
32
+
request_body_wo = jsonencode({
33
+
password = var.password
34
+
})
35
+
request_body_wo_version = 1
36
+
37
+
response_codes = [200]
38
+
skip_read = true
39
+
}
40
+
```
41
+
42
+
Do **not** set both `headers` and `headers_wo` (or `request_body` and `request_body_wo`) on the same operation. TerraCurl rejects conflicting pairs at plan time.
43
+
44
+
## Per-operation attributes
45
+
46
+
| Operation | Headers | Body | Version attributes |
Version attributes are stored in state (not write-only). Increment a `_wo_version` when you change the corresponding write-only value so TerraCurl refreshes the snapshotted credentials on update.
53
+
54
+
## Read and destroy without config access
55
+
56
+
Terraform does not pass resource configuration to Read or Delete RPCs. TerraCurl **snapshots** read/destroy write-only values into provider private state during Create (and refreshes the snapshot on Update when a `_wo_version` changes). Private state is not shown in plan output, but it is persisted with the resource.
57
+
58
+
For rotating destroy credentials without storing them in resource state, consider [provider `default_headers`](default_headers) instead.
59
+
60
+
## Updating write-only values
61
+
62
+
TerraCurl does not re-issue the create HTTP call on in-place update. To change a write-only body or header after initial apply:
63
+
64
+
1. Update the write-only value in configuration
65
+
2. Increment the matching `_wo_version` attribute
66
+
3. Run `terraform apply`
67
+
68
+
If the API must be called again with the new payload, trigger replacement through other attribute changes or taint the resource.
69
+
70
+
## Comparison with other options
71
+
72
+
| Approach | In state? | In plan? | Destroy refresh |
TerraCurl supports write-only `headers_wo` and `request_body_wo` attributes on `terracurl_request` resources (Terraform 1.11+). Values are sent on HTTP calls but are not stored in Terraform state.
169
+
170
+
See the [Write-Only Headers and Request Bodies guide](guides/write_only) for version attributes, read/destroy private-state behavior, and comparison with `default_headers`.
171
+
172
+
```terraform
173
+
# Write-only headers and bodies require Terraform 1.11+.
174
+
#
175
+
# Values are used for HTTP calls but not stored in Terraform state.
176
+
# Increment *_wo_version when changing a write-only value.
Copy file name to clipboardExpand all lines: docs/resources/request.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,6 +25,8 @@ When `skip_read` is `false` and `read_url`, `read_method`, and `read_response_co
25
25
26
26
### Optional
27
27
28
+
> **NOTE**: [Write-only arguments](https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments) are supported in Terraform 1.11 and later.
29
+
28
30
-`ca_cert_directory` (String) Path to a directory on local disk that contains one or more certificate files that will be used to validate the certificate presented by the server
29
31
-`ca_cert_file` (String) Path to a file on local disk that will be used to validate the certificate presented by the server
30
32
-`cert_file` (String) Path to a file on local disk that contains the PEM-encoded certificate to present to the server
@@ -33,10 +35,14 @@ When `skip_read` is `false` and `read_url`, `read_method`, and `read_response_co
33
35
-`destroy_cert_file` (String) Path to a file on local disk that contains the PEM-encoded certificate to present to the server for the destroy call
34
36
-`destroy_digest_auth` (Attributes, Sensitive) HTTP Digest authentication credentials for the destroy request. Overrides provider `default_digest_auth` when configured. (see [below for nested schema](#nestedatt--destroy_digest_auth))
35
37
-`destroy_headers` (Map of String) Map of headers to attach to the destroy API call. Host (case-insensitive) overrides the HTTP Host header sent on the wire, independent of the URL hostname.
38
+
-`destroy_headers_wo` (Map of String, Sensitive, [Write-only](https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments)) Write-only headers for the destroy call. Snapshotted in provider private state for use during destroy.
39
+
-`destroy_headers_wo_version` (Number) Increment to trigger refreshing snapshotted `destroy_headers_wo` values.
36
40
-`destroy_key_file` (String) Path to a file on local disk that contains the PEM-encoded private key for which the authentication certificate was issued for the destroy call
37
41
-`destroy_max_retry` (Number) Maximum number of tries until it is marked as failed for the destroy call
38
42
-`destroy_method` (String) Destroy HTTP method to use in the API call
39
43
-`destroy_request_body` (String) A request body to attach to the destroy API call
44
+
-`destroy_request_body_wo` (String, Sensitive, [Write-only](https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments)) Write-only request body for the destroy call. Not stored in Terraform state.
45
+
-`destroy_request_body_wo_version` (Number) Increment to trigger applying an updated `destroy_request_body_wo` value.
40
46
-`destroy_request_parameters` (Map of String) Map of parameters to attach to the destroy API call
41
47
-`destroy_response_codes` (List of String) A list of expected response codes for the destroy call
42
48
-`destroy_retry_interval` (Number) Interval between each attempt for the destroy call
@@ -45,6 +51,8 @@ When `skip_read` is `false` and `read_url`, `read_method`, and `read_response_co
45
51
-`destroy_url` (String) Destroy API endpoint to call
46
52
-`digest_auth` (Attributes, Sensitive) HTTP Digest authentication credentials for the create request. Overrides provider `default_digest_auth` when configured. (see [below for nested schema](#nestedatt--digest_auth))
47
53
-`headers` (Map of String) Map of headers to attach to the API call. Host (case-insensitive) overrides the HTTP Host header sent on the wire, independent of the URL hostname.
54
+
-`headers_wo` (Map of String, Sensitive, [Write-only](https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments)) Write-only headers for the create call. Not stored in Terraform state. Requires Terraform 1.11 or later.
55
+
-`headers_wo_version` (Number) Increment to trigger applying updated `headers_wo` values.
48
56
-`ignore_response_fields` (List of String) List of JSON fields to ignore during drift detection.
49
57
-`key_file` (String) Path to a file on local disk that contains the PEM-encoded private key for which the authentication certificate was issued
50
58
-`max_retry` (Number) Maximum number of tries until it is marked as failed
@@ -53,14 +61,20 @@ When `skip_read` is `false` and `read_url`, `read_method`, and `read_response_co
53
61
-`read_cert_file` (String) Path to a PEM-encoded certificate for the read request (TLS).
54
62
-`read_digest_auth` (Attributes, Sensitive) HTTP Digest authentication credentials for the read request. Overrides provider `default_digest_auth` when configured. (see [below for nested schema](#nestedatt--read_digest_auth))
55
63
-`read_headers` (Map of String) Map of headers for the read request. Host (case-insensitive) overrides the HTTP Host header sent on the wire, independent of the URL hostname.
64
+
-`read_headers_wo` (Map of String, Sensitive, [Write-only](https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments)) Write-only headers for the read call. Snapshotted in provider private state for drift detection.
65
+
-`read_headers_wo_version` (Number) Increment to trigger refreshing snapshotted `read_headers_wo` values.
56
66
-`read_key_file` (String) Path to a PEM-encoded private key for the read request (TLS).
57
67
-`read_method` (String) HTTP method for reading resource state. Required if `skip_read` is false.
58
68
-`read_parameters` (Map of String) Optional request parameters to add to the URL
59
69
-`read_request_body` (String) Optional request body to use for the read request.
70
+
-`read_request_body_wo` (String, Sensitive, [Write-only](https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments)) Write-only request body for the read call. Snapshotted in provider private state for drift detection.
71
+
-`read_request_body_wo_version` (Number) Increment to trigger refreshing snapshotted `read_request_body_wo` values.
60
72
-`read_response_codes` (List of String) Expected response codes for the read request. Required if `skip_read` is false.
61
73
-`read_skip_tls_verify` (Boolean) Skip TLS verification for the read request.
62
74
-`read_url` (String) API endpoint for reading resource state. Required if `skip_read` is false.
63
75
-`request_body` (String) A request body to attach to the API call
76
+
-`request_body_wo` (String, Sensitive, [Write-only](https://developer.hashicorp.com/terraform/language/resources/ephemeral#write-only-arguments)) Write-only request body for the create call. Not stored in Terraform state. Requires Terraform 1.11 or later.
77
+
-`request_body_wo_version` (Number) Increment to trigger applying an updated `request_body_wo` value.
64
78
-`request_parameters` (Map of String) Map of parameters to attach to the API call
65
79
-`response_sensitive` (Boolean) Set to `true` to treat the response as sensitive. When enabled, the response body is written to `sensitive_response` (a sensitive attribute) and `response` is left empty so that secret values are not displayed in plan output. Defaults to `false` to preserve existing behavior.
66
80
-`retry_interval` (Number) Interval between each attempt
0 commit comments