Skip to content

feat: add security, rate limit and data source coverage - #3

Merged
AlejandroFabianCampos merged 10 commits into
mainfrom
feat/security-resources
Sep 23, 2026
Merged

AlejandroFabianCampos merged 10 commits into
mainfrom
feat/security-resources

Conversation

@AlejandroFabianCampos

@AlejandroFabianCampos AlejandroFabianCampos commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Brings the provider from one resource to the full endpoint surface: security, rate limits, and lookups for endpoints created elsewhere.

What is new

quicknode_endpoint_ip, _domain_mask, _referrer who is allowed to call an endpoint
quicknode_endpoint_jwt signing keys, for authenticating without a token in the URL
quicknode_endpoint_token extra auth tokens, so one consumer can be revoked without disturbing the rest
quicknode_endpoint_request_filter which RPC methods an endpoint accepts
quicknode_endpoint_rate_limits endpoint-wide rps/rpm/rpd, with the plan defaults reported alongside
quicknode_endpoint_method_rate_limit a limit on a named set of methods
data.quicknode_endpoint, data.quicknode_endpoints endpoints created elsewhere, with filtering and full pagination

quicknode_endpoint gains security_options — seven settable toggles plus two the Admin API reports but will not accept on write — and ip_custom_header for endpoints behind a proxy.

Decisions worth reviewing

Separate resources rather than inline sets. An entry added outside Terraform is left alone, and two modules can each contribute one. Inline lists would make the endpoint resource delete anything it did not create, which is the problem aws_security_group inline rules are known for.

Allowlist entries import by value, not by id. 123456/203.0.113.7 is what an operator already knows; the entry id only exists in the API. Import resolves the value against the endpoint's entries and refuses rather than guesses when more than one matches. Request filters and method rate limiters have no natural name so they keep the id, and tokens import by id on purpose, to keep the credential out of shell history.

Adding an entry while its toggle is off warns rather than errors. The API accepts it, and building an allowlist before enabling enforcement is the safe order for an endpoint already serving traffic. The check runs at apply rather than plan: a plan-time read would reject a config that enables the toggle and adds the entry in the same run.

Unmanaged values are omitted from write bodies, never sent as zero. Security toggles are read as booleans and written as the strings enabled and disabled, so a stray false would read as "turn this off". Rate limit buckets have the same hazard. Both write paths take pointers and leave anything unmanaged out of the request; TestSetSecurityOptionsSendsStrings and TestSetRateLimitsOmitsUnmanagedBuckets assert it.

Dropping a rate limit bucket deletes its override. The patch route has no way to say "return this bucket to the plan default", so removing rpm from the configuration issues a delete against the override id rather than leaving it in place.

interval replaces a method rate limiter. The update route takes methods, rate and status but no interval.

Method rate limits keep the casing the configuration wrote. That route lowercases the method names it stores, so reading them back verbatim leaves a diff no apply can settle. Read compares the returned methods to prior state case-insensitively and keeps the configured spelling; a method the prior state does not hold is kept exactly as the API returned it, so a real change is still detected. The request filter route does not normalise, and needs none of this.

tokens stays on quicknode_endpoint. It is purely computed, so it cannot fight quicknode_endpoint_token over ownership, and removing it would break the schema for no gain.

Endpoint URLs

http_url and wss_url are renamed safe_http_url and safe_wss_url, and they now carry the literal TOKEN where the credential belongs instead of having it cut out:

https://example-name.hype-testnet.quiknode.pro/TOKEN/evm

The old form deleted the token segment, which mangled every chain that appends a suffix after it — .../abc123/evm became .../evm, a URL that does not work and cannot be repaired by appending a token. Substituting into the placeholder reproduces a working address on any chain:

replace(quicknode_endpoint.api.safe_http_url, "TOKEN", var.token)

http_url_with_token and wss_url_with_token are unchanged and stay sensitive.

This branch also fixes a leak it introduced: data.quicknode_endpoints mapped the list route's http_url straight through, and that route returns the credentialed URL. It was exposed as a non-sensitive attribute documented as safe to log. It is redacted on ingest now, so the list data source carries only the placeholder form — the credentialed URLs are available from a full endpoint read.

Testing

The acceptance tests have now run against the live Admin API. All eight pass, together with the unit tests: make lint reports no issues.

They found four issues the unit tests could not have caught:

network slug in the test config the Sepolia slug is ethereum-sepolia. The plan-time validator rejected the configuration and named the valid slugs, which is the validator working as intended — the test was wrong
create response ipCustomHeader decoded with the wrong type, so every terraform apply creating an endpoint failed to decode the response
security options patch response data is an array with one {option, status} per toggle changed
method rate limit method names stored lowercase, so eth_getLogs came back eth_getlogs and left a permanent diff

The create failure is worth noting on its own: the endpoint was created and then the response failed to decode, so the provider returned an error and Terraform recorded nothing. That leaves a real endpoint nobody is tracking. CheckDestroy cannot catch it — the resource never reached state — which is exactly why the decode path matters.

CheckDestroy is new here. Terraform treats a destroy as successful as soon as the provider's Delete returns no error, so a delete the API quietly declined would have passed and left a billable endpoint behind. Every test case now asks the API whether the endpoints it created are really gone.

Acceptance tests still run only on workflow_dispatch and still need a QUICKNODE_API_KEY secret, which the repository does not have yet; the job skips until it does.

Spec patches

api/admin/patches.json grows from 14 to 29. Most add item types to arrays (the security lists, the request filter and method rate limit method arrays, and three list-route filter parameters) so the generated client gets typed slices. Both request filter write routes answer 204 with no body, which has separate handling. The last two patches are the create-response and security-options shapes above.

@AlejandroFabianCampos
AlejandroFabianCampos requested a review from a team as a code owner September 22, 2026 22:52
@AlejandroFabianCampos AlejandroFabianCampos changed the title feat: add endpoint security resources and security options feat: add security, rate limit and data source coverage Sep 22, 2026
@AlejandroFabianCampos
AlejandroFabianCampos merged commit ded90d2 into main Sep 23, 2026
4 checks passed
@AlejandroFabianCampos
AlejandroFabianCampos deleted the feat/security-resources branch September 25, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants