Updraft::Config::Document
Reads a JSON or YAML document from Amazon S3 at stack-operation time and makes its contents available to the rest of the template — so configuration can live in a versioned file rather than in fifty template parameters.
Ref returns
Document IDdoc-2f8a1c94Fn::GetAtt
6
attributesMinimal template
Every required property, nothing elseResources:
AppConfig:
Type: Updraft::Config::Document
Properties:
Source:
Bucket: acme-platform-config
Key: environments/production.yaml{
"Resources": {
"AppConfig": {
"Type": "Updraft::Config::Document",
"Properties": {
"Source": {
"Bucket": "acme-platform-config",
"Key": "environments/production.yaml"
}
}
}
}
}Format defaults to Auto, which infers JSON or YAML from the object key’s
extension and falls back to sniffing the first non-whitespace byte. Set it
explicitly when the key has no extension.Overview #
Updraft::Config::Document reads one file from S3 during a stack operation,
parses it, and makes the result available to the rest of the template. It exists
because CloudFormation’s own mechanisms for getting configuration into a
template all scale badly.
Template parameters work for five values and become unmanageable at fifty.
Mappings put the configuration inside the template, so changing one value means
redeploying the template that consumes it. Fn::ImportValue couples stacks so
tightly that an export cannot change while anything imports it. A file in S3 has
none of those problems — it is versioned, reviewable, diffable, and readable by
things that are not CloudFormation.
How resolution works #
Three sources are merged, in a fixed order.
Defaults supplies what the file omits; Overrides wins over both. Redaction runs after the merge, so a redacted value never reaches any attribute.Scalars and arrays replace outright; only objects merge key by key. An array in
the loaded document replaces the whole array from Defaults, which is almost
always what people expect and occasionally not — there is no element-wise array
merge, deliberately, because every system that has one gets asked for a
different one.
Reading a document and using it #
Configuration in S3
# s3://acme-platform-config/environments/production.yaml
retention:
days: 90
tier: STANDARD_IA
database:
host: payments-db.internal.acme.example
port: 5432
featureFlags:
newCheckout: true
legacyExport: false
Template
Resources:
AppConfig:
Type: Updraft::Config::Document
Properties:
Source:
Bucket: acme-platform-config
Key: environments/production.yaml
ExpectedOwner: !Ref AWS::AccountId
VersionId: !Ref ConfigVersion
RetentionDays:
Type: Updraft::Config::Lookup
Properties:
Document: !Ref AppConfig
Path: /retention/days
Type: Number
Default: "30"
!Ref AppConfig
→
doc-2f8a1c94a handle, not the contents
!GetAtt AppConfig.Keys
→
database,featureFlags,retention
!Ref RetentionDays
→
90the resolved value from the lookup
Choosing a freshness strategy #
This resource re-reads the object only when one of its own properties changes. That is a deliberate constraint of the CloudFormation model rather than a limitation of the implementation, and it forces a choice.
| Strategy | Set | Behaviour |
|---|---|---|
| Pinned | VersionId | The template records which configuration it was deployed against. A change to configuration is a template change with a reviewable diff. |
| Token-driven | RefreshToken to a build number or commit SHA | Re-reads on every pipeline run, picking up whatever is current. |
| Bootstrap only | Neither | Read once at create. Later edits to the file are never picked up. |
Properties
Expand a row for the full reference; nested types open in placeSource S3LocationThe S3 object to read. Required No interruption — updates in place
The document is read once per stack operation, by the extension’s own execution role. It is not re-read when the object changes — see Freshness and drift below.- Type
S3Location- Required
- Yes
- Update behaviour
- No interruption
S3Location properties
Bucket StringName of the bucket holding the document. Required No interruption — updates in place
Name of the bucket holding the document.
- Type
String- Required
- Yes
- Update behaviour
- No interruption
- Pattern
^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$S3 bucket naming rules; no uppercase, no underscores.- Length
3 – 63
Example values
acme-platform-config
Key StringObject key, including any prefix. Required No interruption — updates in place
Object key, including any prefix.
- Type
String- Required
- Yes
- Update behaviour
- No interruption
- Length
1 – 1024
Example values
environments/production.yaml
ExpectedOwner StringAccount ID that must own the bucket for the read to proceed. No interruption — updates in place
Account ID that must own the bucket for the read to proceed.
- Type
String- Required
- No
- Update behaviour
- No interruption
- Pattern
^\d{12}$
Example values
123456789012
Region StringRegion of the bucket, when it differs from the stack's region. No interruption — updates in place
Cross-region reads add latency to every stack operation and cross-region data transfer charges to every deployment. Prefer replicating the object to a bucket in the stack’s region.- Type
String- Required
- No
- Update behaviour
- No interruption
Example values
us-east-1
Format StringHow to parse the object body. No interruption — updates in place
Autoinfers from the key’s extension (.json,.yaml,.yml) and falls back to inspecting the first non-whitespace byte:{or[means JSON, anything else is parsed as YAML.- Type
String- Required
- No
- Update behaviour
- No interruption
- Default
Auto
Allowed values
AutoJsonYaml
Defaults JSONA document merged *underneath* the loaded one, supplying values the file omits. No interruption — updates in place
Merged recursively: objects are combined key by key, and any scalar or array in the loaded document replaces its counterpart here outright. Use it to keep environment files small without making every lookup specify a fallback.- Type
JSON- Required
- No
- Update behaviour
- No interruption
Example values
{"retention": {"days": 30}, "featureFlags": {}}
Encoding StringCharacter encoding of the object body. No interruption — updates in place
A byte-order mark, if present, wins over this property. Objects written by Windows tooling frequently carry a UTF-8 BOM that would otherwise become part of the first key name.- Type
String- Required
- No
- Update behaviour
- No interruption
- Default
UTF-8
Allowed values
UTF-8UTF-16LEUTF-16BEISO-8859-1
KmsKeyId StringKMS key to use when the object is encrypted with SSE-KMS. No interruption — updates in place
Only needed when the extension’s execution role reaches the key through a grant rather than through the key policy. SSE-S3 and bucket-default encryption need nothing here.- Type
String- Required
- No
- Update behaviour
- No interruption
Example values
arn:aws:kms:us-west-2:123456789012:key/1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
MaxSizeBytes IntegerRefuse to read objects larger than this. No interruption — updates in place
A guard against a mis-keyedSourcepointing at a log archive. The read is aborted from theContent-Lengthheader before the body is fetched.- Type
Integer- Required
- No
- Update behaviour
- No interruption
- Default
262144- Range
1024 – 4194304
Overrides JSONA document merged *over* the loaded one, taking precedence over the file. No interruption — updates in place
Applied afterDefaultsand after the loaded document. The resolution order isDefaults→ document →Overrides, so an override always wins.- Type
JSON- Required
- No
- Update behaviour
- No interruption
Redact Array of RedactionRulePaths whose values are removed from all attributes and logs. No interruption — updates in place
Redaction happens immediately after parsing and before anything else can observe the document. Redacted paths still contribute toChecksum, so a change to a secret still invalidates caches without revealing the secret.- Type
Array of RedactionRule- Required
- No
- Update behaviour
- No interruption
- Items
0 – 50
RedactionRule properties
Path StringJSON Pointer to the value to redact. Supports a trailing wildcard. Required No interruption — updates in place
JSON Pointer to the value to redact. Supports a trailing wildcard.
- Type
String- Required
- Yes
- Update behaviour
- No interruption
Example values
/database/password/tenants/*/apiKey
Strategy StringWhat to replace the value with. No interruption — updates in place
Removedeletes the key entirely — a downstreamLookupreports it as not found.Nullkeeps the key with a null value, which preserves the document’s shape for schema validation.Maskreplaces a string with the same number of*characters, preserving length only.- Type
String- Required
- No
- Update behaviour
- No interruption
- Default
Remove
Allowed values
RemoveMask
RefreshToken StringAn arbitrary value whose change forces the document to be re-read. No interruption — updates in place
The value is never interpreted. Its only job is to give CloudFormation a property diff so the handler runs again.- Type
String- Required
- No
- Update behaviour
- No interruption
Example values
build-48212026-08-09T14:00:00Z
Required BooleanWhether a missing object fails the stack operation. No interruption — updates in place
Whenfalse, aNoSuchKeyresponse is treated as an empty document, andDefaultsalone determines the contents. TheFoundattribute reports which happened.- Type
Boolean- Required
- No
- Update behaviour
- No interruption
- Default
true
Schema SchemaValidationValidate the loaded document before any other resource can read it. No interruption — updates in place
Validation failures fail the stack operation with the offending JSON pointer in the status reason, which is considerably easier to act on than a downstream resource failing on an unexpectednull.- Type
SchemaValidation- Required
- No
- Update behaviour
- No interruption
SchemaValidation properties
Inline JSONThe JSON Schema document, written directly in the template. Conditional No interruption — updates in place
The JSON Schema document, written directly in the template.
- Type
JSON- Required
- ConditionalExactly one of
InlineorSourcemust be set. - Update behaviour
- No interruption
Source S3LocationAn S3 object holding the JSON Schema document. Conditional No interruption — updates in place
An S3 object holding the JSON Schema document.
- Type
S3Location- Required
- ConditionalExactly one of
InlineorSourcemust be set. - Update behaviour
- No interruption
S3Location properties
Bucket StringName of the bucket holding the document. Required No interruption — updates in place
Name of the bucket holding the document.
- Type
String- Required
- Yes
- Update behaviour
- No interruption
- Pattern
^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$S3 bucket naming rules; no uppercase, no underscores.- Length
3 – 63
Example values
acme-platform-config
Key StringObject key, including any prefix. Required No interruption — updates in place
Object key, including any prefix.
- Type
String- Required
- Yes
- Update behaviour
- No interruption
- Length
1 – 1024
Example values
environments/production.yaml
ExpectedOwner StringAccount ID that must own the bucket for the read to proceed. No interruption — updates in place
Account ID that must own the bucket for the read to proceed.
- Type
String- Required
- No
- Update behaviour
- No interruption
- Pattern
^\d{12}$
Example values
123456789012
Region StringRegion of the bucket, when it differs from the stack's region. No interruption — updates in place
Cross-region reads add latency to every stack operation and cross-region data transfer charges to every deployment. Prefer replicating the object to a bucket in the stack’s region.- Type
String- Required
- No
- Update behaviour
- No interruption
Example values
us-east-1
AllowAdditionalProperties BooleanWhether keys absent from the schema are permitted. No interruption — updates in place
Setting this tofalseturns a typo in a configuration key from a silently-ignored line into a failed deployment, which is usually what you want for a file that gates production behaviour.- Type
Boolean- Required
- No
- Update behaviour
- No interruption
- Default
true
Draft StringJSON Schema dialect to validate against. No interruption — updates in place
JSON Schema dialect to validate against.
- Type
String- Required
- No
- Update behaviour
- No interruption
- Default
2020-12
Allowed values
072019-092020-12
VersionId StringPin the read to a specific S3 object version. No interruption — updates in place
Without a version, the document is read at whatever state the key is in when the stack operation runs. Two stacks deployed an hour apart can therefore see different configuration from the same template — which is usually the point, and occasionally a very unpleasant surprise.- Type
String- Required
- No
- Update behaviour
- No interruption
- Length
0 – 1024
Example values
3HL4kqtJlcpXroDTDmJ.Vjlh5Wm5cJ8
| Property | Type | Required | Update | Description |
|---|---|---|---|---|
| Source | S3Location | Yes | None | The S3 object to read. |
| Source.Bucket | String | Yes | None | Name of the bucket holding the document. |
| Source.Key | String | Yes | None | Object key, including any prefix. |
| Source.ExpectedOwner | String | No | None | Account ID that must own the bucket for the read to proceed. |
| Source.Region | String | No | None | Region of the bucket, when it differs from the stack's region. |
| Format | String | No | None | How to parse the object body. |
| Defaults | JSON | No | None | A document merged *underneath* the loaded one, supplying values the file omits. |
| Encoding | String | No | None | Character encoding of the object body. |
| KmsKeyId | String | No | None | KMS key to use when the object is encrypted with SSE-KMS. |
| MaxSizeBytes | Integer | No | None | Refuse to read objects larger than this. |
| Overrides | JSON | No | None | A document merged *over* the loaded one, taking precedence over the file. |
| Redact | Array of RedactionRule | No | None | Paths whose values are removed from all attributes and logs. |
| Redact.Path | String | Yes | None | JSON Pointer to the value to redact. Supports a trailing wildcard. |
| Redact.Strategy | String | No | None | What to replace the value with. |
| RefreshToken | String | No | None | An arbitrary value whose change forces the document to be re-read. |
| Required | Boolean | No | None | Whether a missing object fails the stack operation. |
| Schema | SchemaValidation | No | None | Validate the loaded document before any other resource can read it. |
| Schema.Inline | JSON | Conditional | None | The JSON Schema document, written directly in the template. |
| Schema.Source | S3Location | Conditional | None | An S3 object holding the JSON Schema document. |
| Schema.Source.Bucket | String | Yes | None | Name of the bucket holding the document. |
| Schema.Source.Key | String | Yes | None | Object key, including any prefix. |
| Schema.Source.ExpectedOwner | String | No | None | Account ID that must own the bucket for the read to proceed. |
| Schema.Source.Region | String | No | None | Region of the bucket, when it differs from the stack's region. |
| Schema.AllowAdditionalProperties | Boolean | No | None | Whether keys absent from the schema are permitted. |
| Schema.Draft | String | No | None | JSON Schema dialect to validate against. |
| VersionId | String | No | None | Pin the read to a specific S3 object version. |
Generated from the schema. The first pair shows only required and conditionally-required properties — a template you can paste and deploy. Property keys are ordered alphabetically here rather than required-first, because that is the order a template file conventionally uses.
Type: Updraft::Config::Document
Properties:
Source:
Bucket: acme-platform-config
Key: environments/production.yaml{
"Type": "Updraft::Config::Document",
"Properties": {
"Source": {
"Bucket": "acme-platform-config",
"Key": "environments/production.yaml"
}
}
}Every property, three levels deep:
Type: Updraft::Config::Document
Properties:
Defaults: '{"retention": {"days": 30}, "featureFlags": {}}'
Encoding: UTF-8
Format: Auto
KmsKeyId: arn:aws:kms:us-west-2:123456789012:key/1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
MaxSizeBytes: 262144
Overrides:
Key: Value
Redact:
- Path: /database/password
Strategy: Remove
RefreshToken: build-4821
Required: true
Schema:
AllowAdditionalProperties: true
Draft: 2020-12
Inline:
Key: Value
Source:
Bucket: acme-platform-config
ExpectedOwner: '123456789012'
Key: environments/production.yaml
Region: us-east-1
Source:
Bucket: acme-platform-config
ExpectedOwner: '123456789012'
Key: environments/production.yaml
Region: us-east-1
VersionId: 3HL4kqtJlcpXroDTDmJ.Vjlh5Wm5cJ8{
"Type": "Updraft::Config::Document",
"Properties": {
"Defaults": "{\"retention\": {\"days\": 30}, \"featureFlags\": {}}",
"Encoding": "UTF-8",
"Format": "Auto",
"KmsKeyId": "arn:aws:kms:us-west-2:123456789012:key/1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"MaxSizeBytes": 262144,
"Overrides": {
"Key": "Value"
},
"Redact": [
{
"Path": "/database/password",
"Strategy": "Remove"
}
],
"RefreshToken": "build-4821",
"Required": true,
"Schema": {
"AllowAdditionalProperties": true,
"Draft": "2020-12",
"Inline": {
"Key": "Value"
},
"Source": {
"Bucket": "acme-platform-config",
"ExpectedOwner": "123456789012",
"Key": "environments/production.yaml",
"Region": "us-east-1"
}
},
"Source": {
"Bucket": "acme-platform-config",
"ExpectedOwner": "123456789012",
"Key": "environments/production.yaml",
"Region": "us-east-1"
},
"VersionId": "3HL4kqtJlcpXroDTDmJ.Vjlh5Wm5cJ8"
}
}Return values
What other resources can read from this oneRefUpdraft::Config::Lookup and Updraft::Config::ParameterSet rather than
repeating the Source block.!Ref MyResource
→
doc-2f8a1c94
Fn::GetAtt attributes
| Attribute | Type | Description | Example value |
|---|---|---|---|
| Checksum | String | SHA-256 of the merged, redacted document in canonical form. Changes whenever effective configuration changes. | 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 |
| ContentLength | Integer | Size of the object body in bytes, before merging. | 2481 |
| Found | Boolean | Whether the object existed. Always true unless Required is false. | true |
| Keys | Array | Top-level keys present in the merged document, sorted. Useful for assertions and for debugging a merge. | ["database","featureFlags","retention"] |
| LastModified | String | The object’s S3 last-modified timestamp, in RFC 3339. | 2026-07-14T09:12:44Z |
| ResolvedVersionId | String | The S3 object version actually read — the pinned version, or the current one at read time. Record this in a stack output to know what a deployment saw. | 3HL4kqtJlcpXroDTDmJ.Vjlh5Wm5cJ8 |
Required permissions
For the principal running the stack operationcreate
- s3:GetObject
- s3:GetObjectVersion
- s3:ListBucket
- kms:Decrypt
read
- s3:GetObject
- s3:ListBucket
update
- s3:GetObject
- s3:GetObjectVersion
- s3:ListBucket
- kms:Decrypt
delete
No actions required
{
"Statement": [
{
"Action": [
"kms:Decrypt",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "*",
"Sid": "ManageResource"
}
],
"Version": "2012-10-17"
}Statement:
- Action:
- kms:Decrypt
- s3:GetObject
- s3:GetObjectVersion
- s3:ListBucket
Effect: Allow
Resource: '*'
Sid: ManageResource
Version: '2012-10-17'