Dstack-TEE / Dstack-TEE/dstack-examples

Feature: ACME DNS-01 challenge delegation (CNAME alias) for least-privilege DNS tokens

Ouverte
#103 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub
Langage dominant
Python
Étoiles
27
Forks
26
Merge moyen
1 h 25 min
PR mergées (30 j)
7

Description

## Problem

dstack-ingress issues certs via ACME **DNS-01**, which requires a DNS provider API token that can edit the **served domain's own zone** (to write the `_acme-challenge` TXT, and — per `entrypoint.sh` — to set the A record and CAA).

In our deployment the served name (e.g. `svc.example.com`) lives under a **shared production zone** (`example.com`) that holds many unrelated production records. Handing the enclave a token for that zone is too broad:

- Cloudflare API tokens scope only to **zone level** — there is no way to restrict a token to a single subdomain/record.
- Managing the subdomain as its own Cloudflare zone requires an **Enterprise** plan.

So today we'd have to give the enclave a token that can edit our **entire** `example.com` zone, which we can't accept.

## Proposed feature: DNS-01 challenge delegation (CNAME alias)

Let the operator delegate **only the `_acme-challenge`** to a separate zone they fully control, so the enclave's token never touches the production zone:

1. Operator adds one static record in the production zone:
`_acme-challenge.svc.example.com CNAME .`
2. dstack-ingress writes the challenge TXT into `` (its token scoped **only** to that zone). Let's Encrypt follows the CNAME during validation.

This is a standard least-privilege ACME pattern (acme.sh `--challenge-alias`, lego, cert-manager, and Cloudflare's own "Delegated DCV" all support it), and it fits dstack's zero-trust ethos.

## Design sketch (opt-in, non-breaking)

- New env `ACME_CHALLENGE_ALIAS=`; unset ⇒ current behavior, unchanged.
- When set, run certbot with `--manual --preferred-challenges=dns` + auth/cleanup hooks that **reuse the existing `dns_providers` abstraction** to write the TXT under the alias zone instead of `_acme-challenge.`.

## Important: CAA handling (needs an explicit decision)

`entrypoint.sh` currently auto-sets the accounturi CAA
(`letsencrypt.org;validationmethods=dns-01;accounturi=$ACCOUNT_URI`) on the served domain, using the same token. In delegation mode the token **cannot** touch the served domain's zone, so this auto-set won't work — and the current code treats a CAA-set failure as `not critical`, which would **silently drop the accounturi lock** (the forge-prevention against a non-TEE account issuing a cert for the domain).

To avoid silently weakening security, in delegation mode the feature should:
- **print the exact CAA record** the operator must set statically in the served zone (including the account URI), and
- **verify the CAA is present / warn loudly if absent**, instead of silently continuing.

This keeps the "only the TEE's ACME account can issue" guarantee **explicit**, rather than silently lost.

Guide de contribution

Ouvrir le guide de contribution

Piste de recherche

Start with entrypoint.sh and the existing dns_providers abstraction; trace the current ACME invocation, TXT handling, and CAA failure path. Review the proposed ACME_CHALLENGE_ALIAS flow and certbot manual auth/cleanup hooks. Done means alias-zone TXT delegation works without production-zone access, while the exact accounturi CAA is printed and verified or loudly reported absent.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python, shell
Domaine
cloud, devops, security
Type d'issue
Fonctionnalité
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
Calme
Clarté
Plutôt claire
Accessibilité débutants
45/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.