Implement providers.aws.sign_req builtin - #151
Conversation
…loses open-policy-agent#146) Signed-off-by: Muhammad Umer Hammad <umerhammad010@gmail.com>
sspaink
left a comment
There was a problem hiding this comment.
Verified against OPA's topdown/providers.go + internal/providers/aws/signing_v4.go, with the divergences below confirmed by running Go directly. The SigV4 chain, string-to-sign, credential scope, header precedence (including the subtle "existing x-amz-content-sha256 wins in the canonical request but computed hash wins in output"), raw_body precedence, and error-message wording all match, and the fixture-driven test is solid. Because signing is byte-exact, the findings all manifest as wrong signatures on inputs the 18 fixtures don't cover — so the suite passes while real requests would fail AWS verification. Findings 1 and 3 share a root cause: canonicalJson reimplements Go's encoding/json and misses two of its behaviors.
| // disable_payload_signing (optional boolean). | ||
| boolean disablePayloadSigning = false; | ||
| RegoValue dps = awsConfigObj.getProperty("disable_payload_signing"); | ||
| if (dps != null) { |
There was a problem hiding this comment.
(minor) Negative time_ns is rejected where OPA accepts it. The ts < 0 guard throws TypeError, but OPA does time.Unix(0, ts), which happily produces a pre-1970 signing time. Divergence only for negative timestamps — unlikely in practice, flagging for completeness.
There was a problem hiding this comment.
Looked into matching time.Unix(0, ts) exactly, but the existing failure-simple-bad timestamp fixture explicitly expects -1e9 to throw an error, so this change breaks that fixture. Since you flagged it as minor, I held off changing shared test data unilaterally, happy to update both the code and the fixture if you'd rather match Go exactly here too.
There was a problem hiding this comment.
The fixture isn't rejecting -1e9 for being negative — OPA's timestamp.Int64() is strconv.ParseInt(literal, 10, 64), which rejects any literal that isn't a plain base-10 integer. Confirmed against the binary: -1e9 errors but -1000000000 signs fine (19691231T235959Z), while 1e9 and 1.0 both error. So ts < 0 satisfies the fixture by coincidence and is wrong in both directions — it rejects valid negative integers and accepts 1e9/1.0, which OPA rejects.
The correct gate is the number's literal form rather than its value, which needs RegoDecimal/RegoBigInt to retain the source text (same root cause as the float-body thread). Fine as a follow-up rather than a blocker — but worth reopening, since the fixture is currently passing for the wrong reason.
… formatting to match Go byte-exactly Signed-off-by: Muhammad Umer Hammad <umerhammad010@gmail.com>
| private void validateHttpRequestOperand(RegoObject reqObj) { | ||
| List<String> missing = new ArrayList<>(); | ||
| for (String key : REQUIRED_REQUEST_KEYS) { | ||
| if (reqObj.getProperty(key) == null) { | ||
| missing.add(key); | ||
| } | ||
| } | ||
| if (!missing.isEmpty()) { | ||
| throw new TypeError( | ||
| "operand 1 missing required request parameters(s): " + formatKeySet(missing)); | ||
| } | ||
| } |
There was a problem hiding this comment.
validateHTTPRequestOperand also rejects keys outside http.send's allowedKeyNames whitelist, and that check runs before the missing-keys check (http.go:311) — so {"url": ..., "method": ..., "bogus_key": "x"} errors in OPA but signs successfully here. The whitelist is the 28-entry allowedKeyNames list, and note the invalid-keys error needs to precede the missing-keys one to match OPA's ordering.
…missing-key check Signed-off-by: Muhammad Umer Hammad <umerhammad010@gmail.com>
Summary
Implements providers.aws.sign_req (AWS SigV4 header-based request signing) as described in #146.
Changes
Testing
Closes #146.