New: HMAC Request Signing
The new hmac_sign transform signs outbound requests with HMAC before forwarding them upstream. Algorithm (sha256, sha512, sha1), key encoding, output encoding, timestamp format, and the signed message template are all configurable. The signed message is a Go template with access to .Timestamp, .Method, .Path, .PathWithQuery, .Query, .Host, and .Body. Headers are injected in declaration order and preserve user-specified casing on the wire. Credentials (including the HMAC key) resolve through the existing secrets sources — env, AWS Secrets Manager, SSM, and 1Password all work.
Because a truncated body would produce an invalid signature, the transform enforces body integrity: requests whose buffered body falls short of Content-Length (truncated by proxy.max_request_body_bytes) are rejected with 413, and chunked bodies are rejected with 400 unless allow_chunked_body: true is set. Requires MITM mode.
- name: hmac_sign
config:
timestamp:
format: unix_seconds # unix_seconds | unix_millis | unix_nanos | rfc3339
signature:
algorithm: sha256 # sha256 | sha512 | sha1
key_encoding: base64 # raw | base64 | hex
output_encoding: base64 # base64 | hex
# Go template. Available: .Timestamp .Method .Path .PathWithQuery .Query .Host .Body
message: "{{.Timestamp}}{{.Method}}{{.PathWithQuery}}{{.Body}}"
credentials:
key: {type: env, var: FALCONX_API_KEY}
secret: {type: env, var: FALCONX_SECRET} # required: the HMAC key
passphrase: {type: env, var: FALCONX_PASSPHRASE}
headers: # ordered list — case is preserved on the wire
- {name: "FX-ACCESS-KEY", value: "{{.Credentials.key}}"}
- {name: "FX-ACCESS-SIGN", value: "{{.Signature}}"}
- {name: "FX-ACCESS-TIMESTAMP", value: "{{.Timestamp}}"}
- {name: "FX-ACCESS-PASSPHRASE", value: "{{.Credentials.passphrase}}"}
# allow_chunked_body: false # opt-in to signing chunked (no Content-Length) bodies
rules:
- host: "api.falconx.io"