From the makers of DNScale: PostScale, reliable email delivery for developers. PostScale

    Sign Up
    Product Updates

    DNS-name-scoped API keys — a smaller blast radius for automation

    Create DNScale API keys that can touch only selected zones or exact DNS owner names such as _acme-challenge.

    DNScale API keys have always been customer-wide. If you handed a key to a CI pipeline, a teammate, or a partner agency, that key could read and write every zone on the account. Fine for small setups, uncomfortable once you run a few different brands, clients, or environments behind a single DNScale account.

    Zone-scoped API keys now support an additional boundary: for each selected zone, you can grant the whole zone or only exact DNS owner names. An ACME key can therefore manage _acme-challenge without gaining write access to www, mail records, or the zone itself.

    Why we built it

    A few patterns kept coming up:

    • CI for one app shouldn't manage DNS for the whole company. A staging-deploy pipeline for api.staging.acme.app has no business editing records on payroll.acme.corp, but with a customer-wide key one leaked CI secret exposed both.
    • Agencies managing DNS for multiple clients want to give each client a key that only sees their own zones — no cross-client visibility, no mistakes during script execution.
    • Third-party tooling (monitoring, IaC modules, webhook handlers) rarely needs access to anything beyond the zone it's provisioning for. Least privilege should be the default, not a best-effort convention.

    Zone scope is the missing knob.

    How it works

    When you create an API key in the dashboard, there's a new section:

    Zone and DNS name scope ◉ All zones — key can access every zone in this account. ○ Specific zones — choose each zone, then allow all DNS names or a list of exact names.

    For a names-restricted zone, enter relative names such as _acme-challenge or _acme-challenge.api. Use @ for the apex. Matching is exact and case-insensitive: _acme-challenge does not include _acme-challenge.api, and * means only the literal wildcard owner. Existing keys are unaffected.

    The resource policy is loaded when the key is authenticated and enforced in route middleware, record handlers, and the PowerDNS service. A request outside the policy gets a 403. Record lists are filtered before pagination, so their totals never reveal records outside the key's scope.

    What changes for a zone-scoped key

    Zone scope layers on top of the existing scopes enum (zones:read, records:write, and friends). A zone-scoped key still needs the right scopes to do anything; it just can't reach across zones.

    EndpointCustomer-wide keyWhole-zone scopeDNS-name scope
    GET /zoneslists all zoneslists scoped zoneslists parent zones
    GET /zones/:id/recordsall recordsall records in zoneallowed names only
    Record create/update/deleteany allowed zone/nameany name in zoneexact allowed names only
    Zone update/deleteallowedalloweddenied 403
    DNSSEC, zone access, zone usageallowedalloweddenied 403
    POST /zonesalloweddenied 403denied 403
    Customer-wide usage, billing, users, API keysalloweddenied 403denied 403

    The rule of thumb: the action scope says what the key may do, while the resource policy says where. Both checks must pass.

    One subtlety worth calling out: the zone boundary beats the admin scope. An admin+zone-scoped key is still confined to its zones. Admin scope bypasses scope checks, not zone boundaries. That's the whole point of the feature.

    A concrete example

    Say you run acme.com, acme.dev, and a dozen client zones in the same DNScale account. You're wiring up Terraform for your staging environment and want a key that only acme.dev CI can use.

    1. Dashboard → API Keys → Generate API Key.
    2. Name it ci-staging-acme-dev. Tick zones:read, records:read, records:write.
    3. Zone scope: Specific zones → tick acme.dev → choose Only specific DNS names → enter _acme-challenge and any child challenge owners the client needs.
    4. Create, copy the key into your CI secret store.

    Now:

    # This works — the exact owner is in scope.
    curl -H "Authorization: Bearer $CI_KEY" \
      -X POST https://api.dnscale.eu/v1/zones/<acme-dev-id>/records \
      -d '{"name":"_acme-challenge","type":"TXT","content":"challenge","ttl":300}'
     
    # This 403s — www is not an allowed owner in acme.dev.
    curl -H "Authorization: Bearer $CI_KEY" \
      -X POST https://api.dnscale.eu/v1/zones/<acme-dev-id>/records \
      -d '{"name":"www","type":"A","content":"192.0.2.1","ttl":300}'
     
    # This 403s — creating new zones would escape scope.
    curl -H "Authorization: Bearer $CI_KEY" \
      -X POST https://api.dnscale.eu/v1/zones \
      -d '{"name":"new-zone.com"}'
     
    # GET /zones returns only acme.dev — acme.com and client zones are hidden.
    curl -H "Authorization: Bearer $CI_KEY" https://api.dnscale.eu/v1/zones

    If $CI_KEY leaks, the blast radius is one zone instead of your entire account. Rotate that one key, done.

    Patterns we'd recommend

    • One key per pipeline, per environment. ci-staging-acme-dev, ci-prod-acme-com, terraform-client-x. Small keys with narrow names beat big keys with broad names every time.
    • Pair exact names with narrow permissions. A DNS-01 key usually needs zones:read, records:read, and records:write, plus each exact challenge owner — not zones:write or dnssec:write.
    • Keep one admin-ish customer-wide key for humans and ops tooling, scope everything else. Nothing prevents you from using both.
    • Audit regularly. The dashboard shows "All zones" vs "Scoped to N zones" in the key list. If a key that shouldn't have customer-wide reach still shows "All zones", that's your signal to replace it. Name-scoped entries show their exact owner count and full list on hover.

    Rollout and compatibility

    Resource scoping is locked at creation time in this first version — you pick the zones and exact DNS names when the key is generated, and they stay fixed for the life of the key. If you need to change the scope, create a new key and rotate. We'll look at editable scope once the patterns settle.

    Existing API keys are not touched. If you never create a scoped key, nothing about your integration changes.


    DNS-name scoping is live now. If you've been holding off on handing an API key to a pipeline, a client, or an automation script because it felt too broad, this is the version to try.

    Managed authoritative DNS

    Run DNS with observability built in

    Start free, then move to Scale or custom plans when you need DNS traffic alerts, higher query volume, and dedicated human support.

    More from Product Updates