Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
WORKING_DIR: 'src'
RUST_TOOLCHAIN: '1.96.0' # keep in sync with src/rust-toolchain.toml
NODE_VERSION: '22.x'
PYTHON_VERSION: '3.12'
PYTHON_VERSION: '3.9'
GO_VERSION: '1.26'
UNIFFI_BINDGEN_GO_TAG: 'v0.7.1+v0.31.0' # keep in sync with bindings-go/README.md and the uniffi pin in bindings-go/Cargo.toml
JAVA_VERSION: '21'
Expand Down
6 changes: 3 additions & 3 deletions INSTALLATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ See the [Node.js API and examples](src/bindings-wasm/README.md).
### Python

Production versions are published to [PyPI](https://pypi.org/project/cloudformation-validate/); prereleases are
published to [TestPyPI](https://test.pypi.org/project/cloudformation-validate/). The package requires Python 3.12 or
published to [TestPyPI](https://test.pypi.org/project/cloudformation-validate/). The package requires Python 3.9 or
later, and its platform-specific wheels have no runtime package dependencies.

```bash
Expand Down Expand Up @@ -95,7 +95,7 @@ See the [Go API and examples](src/bindings-go/README.md).

The JVM library is published to
[Maven Central as `software.amazon.cloudformation:cloudformation-validate`](https://central.sonatype.com/artifact/software.amazon.cloudformation/cloudformation-validate)
and requires JDK 21 or later. The jar includes native libraries for all supported platforms; Maven or Gradle resolves
and requires Java 8 or later. The jar includes native libraries for all supported platforms; Maven or Gradle resolves
JNA, Gson, and the Kotlin standard library.

Gradle (Kotlin DSL):
Expand Down Expand Up @@ -185,7 +185,7 @@ testing the project from source need the tools below. Pinned versions live in
| Kotlin (`kotlinc`) | 2.4.0 | JVM binding build | |
| `ktlint` | 1.8.0 | JVM binding formatting | |
| Gradle | 9.6.1 | JVM binding build/test | Must be on `PATH` - `bindings-jvm/build.sh` and the JVM test runner invoke `gradle` |
| Python | 3.12+ | Python binding build/test, license generation, `scripts/` | `setuptools` for the wheel build; no other packages required |
| Python | 3.9+ | Python binding build/test, license generation, `scripts/` | `setuptools` for the wheel build; no other packages required |
| Go | 1.26+ | Go binding build/test | cgo must be enabled (default); Windows also needs `rustup target add x86_64-pc-windows-gnu` and MinGW-w64 `gcc` |
| `uniffi-bindgen-go` | 0.7.1 | Go binding generation | `cargo install --git https://github.com/NordSecurity/uniffi-bindgen-go --tag v0.7.1+v0.31.0` |
| `git`, `curl`, `openssl` | - | source control, fetching JVM deps, verifying releases | Usually preinstalled |
77 changes: 77 additions & 0 deletions src/bindings-go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ diagnostics for the same template and config. A `nil` config uses only the built
| `ValidateStandardFile(path string, config *ValidateConfig)` | `(*StandardReport, error)` | Reads a template from disk, then validates it |
| `ValidateDetailed(template []byte, config *ValidateConfig, filePath string)` | `(*DetailedReport, error)` | Validates bytes with documentation URLs, rule descriptions, phase tags, and `ViolationContext` |
| `ValidateDetailedFile(path string, config *ValidateConfig)` | `(*DetailedReport, error)` | Reads a template from disk, then validates it (detailed) |
| `ValidateAWSAPIRequest(request AWSAPIRequest, config *ValidateConfig)` | `(*AWSAPIRequestValidation, error)` | Classifies and validates an AWS API request offline |
| `ListRules()` | `([]RuleInfo, error)` | Returns metadata for every built-in and loaded custom rule |
| `EngineName()` | `string` | `"rego"` or `"cel"` |
| `Destroy()` | - | Releases the native engine; the engine must not be used afterwards |
Expand Down Expand Up @@ -194,6 +195,82 @@ type PseudoParameterOverrides struct {
}
```

## AWS API Request Validation

Validates an AWS API request by classifying the operation, inferring the CloudFormation resource type, and running
schema and rule validation against a synthesized template - entirely offline. The method returns classification
metadata and an optional `StandardReport` when the request was validated (not skipped for read-only operations).

```go
engine, _ := cfnvalidate.NewRegoEngine(nil)
defer engine.Destroy()

result, err := engine.ValidateAWSAPIRequest(cfnvalidate.AWSAPIRequest{
ServiceName: "s3",
OperationName: "CreateBucket",
Parameters: map[string]any{"Bucket": "my-bucket"},
HTTPMethod: "PUT",
}, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Kind: %s Status: %s Types: %v\n",
result.OperationKind, result.Status, result.ResourceTypes)
if result.Report != nil {
for _, d := range result.Report.Diagnostics {
fmt.Printf(" [%s] %s: %s\n", d.Severity, d.RuleID, d.Message)
}
}
```

### AWSAPIRequest

```go
type AWSAPIRequest struct {
ServiceName string // canonical botocore service name (e.g. "s3") - ASCII case-insensitive
OperationName string // operation name (e.g. "CreateBucket") - case-sensitive
Parameters map[string]any // request parameters: strings, numbers, booleans, []byte, maps, slices, nil
ServicePrefix string // optional signing prefix (e.g. "cloudcontrolapi")
HTTPMethod string // optional HTTP method hint for classification
IsReadOnly *bool // explicit read-only flag - skips validation when true
}
```

`Parameters` values are recursively encoded into the core's tagged value representation. Supported Go types: `nil`,
`bool`, all signed/unsigned integer widths, `float32`/`float64` (finite only), `string`, `[]byte` (as byte arrays),
`time.Time` (as an RFC 3339 UTC string), `json.Number`, slices/arrays, and `map[string]any`. Integer-valued
`json.Number` inputs are preserved across the full signed and unsigned 64-bit range; integer literals outside that range
are represented as unsupported rather than rounded through `float64`. SDK-defined type aliases (e.g.
`types.InstanceType` which is `type InstanceType string`) are handled transparently via their underlying kind.
Non-finite floats, maps with non-string keys, and unsupported types are represented as `UNSUPPORTED` rather than
coerced.

The canonical `ServiceName` is authoritative; the optional `ServicePrefix` is context only and cannot override it.
`ServiceName` must be the exact canonical botocore service name, normalized only for ASCII case. The core does not
guess signing, endpoint, or punctuation aliases and never matches on substrings. Any caller, including a future AWS
SDK adapter in any language, must translate its native service identity to the canonical botocore `ServiceName` before
invoking this API. `TemplateBody` validation is restricted to CloudFormation operations that accept it, and
`TypeName`+`DesiredState` wrapping applies only to exact Cloud Control `CreateResource`.

### AWSAPIRequestValidation

```go
type AWSAPIRequestValidation struct {
OperationKind AWSAPIOperationKind // READ_ONLY, CLOUD_FORMATION_CREATE, etc.
Status AWSAPIRequestValidationStatus // VALIDATED or SKIPPED
TemplateSource *AWSAPITemplateSource // TEMPLATE_BODY, SYNTHESIZED_CREATE, etc.
ResourceTypes []string // inferred CloudFormation resource types
Reason string // human-readable explanation
Report *StandardReport // present only when Status is VALIDATED
Template []byte // exact validated/synthesized template bytes; nil when SKIPPED
}
```

`Template` carries the exact bytes that were validated - the caller's original `TemplateBody` without reserializing, or
the synthesized JSON template for adapter-mapped requests - so consumers can display the modeled template that produced
the diagnostics. It is nil when the request was skipped. The core serializes these bytes as a JSON integer array, which
the Go decoder converts back into a `[]byte`.

## TemplateModel

Parses a template into the resolved `SemanticModel` for direct inspection - the same model the engines evaluate rules
Expand Down
Loading