> ## Documentation Index
> Fetch the complete documentation index at: https://certplane.kippel.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Cómo funciona Certplane

> Un flujo en dos fases — registro y renovación — en el que cada host prueba su identidad al broker, que aplica la política y llama a tu CA pública vía ACME.

Certplane divide la gestión de certificados en dos fases. En la primera, un host prueba su identidad a una CA interna y recibe un certificado de identidad de larga duración. En la segunda, ese certificado actúa como credencial cuando el host conecta con el broker para solicitar certificados de servicio públicos. Las claves privadas de servicio nunca salen del host.

## Los dos binarios

| Binario            | Rol                                                                                                                                                                                                                                                                 |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `certplane-broker` | API HTTPS central. Autentica agentes con mTLS, aplica política, habla con el emisor ACME configurado, cachea certificados en un almacén SQLite o de archivo y registra eventos de auditoría.                                                                        |
| `certplane-agent`  | Binario one-shot en cada host gestionado. Se registra con `step-ca` una vez y, en cada invocación, renueva la identidad (si toca), genera o reutiliza claves de servicio localmente, envía CSR al broker, instala los bundles devueltos y ejecuta hooks de recarga. |

Ambos binarios se configuran con un único YAML pasado con `-c` / `--config`.

## Fase 1: registro

Ocurre una vez por host. Vincula el host a su identidad de máquina.

<Steps>
  <Step title="Coloca un token de arranque">
    Un operador (o un play de Ansible) escribe un token de `step-ca` corto en la ruta indicada por `identity.bootstrap_token`.
  </Step>

  <Step title="Ejecuta `certplane-agent ... enroll`">
    El agente toma un lock en `state_dir/agent.lock` y:

    1. Genera una clave ECDSA P-256 en `identity.key` (si no existe).
    2. Construye un CSR con `CN = identity.name`.
    3. Llama al endpoint provisioner de `step-ca` en `identity.step_ca.url`, presentando el CSR y el token. Verifica el TLS del servidor con `identity.step_ca.fingerprint` o `identity.step_ca.root_ca_bundle`.
    4. Escribe el certificado devuelto en `identity.cert` y **borra el archivo del token** para que no pueda reutilizarse.
  </Step>

  <Step title="Identidad establecida">
    El agente posee el par `(identity.key, identity.cert)` firmado por `step-ca`. El CN es la identidad estable usada en cada llamada al broker.
  </Step>
</Steps>

## Fase 2: bucle de renovación

Cada invocación de `certplane-agent ... run` hace lo siguiente:

<Steps>
  <Step title="Renovación de identidad">
    Si el certificado de identidad expira dentro de `identity.renew_before` (por defecto `8h`), el agente renueva con `step-ca` y escribe un `identity.crt` nuevo. Si queda menos de `identity.warn_before` pero aún no hay que renovar, registra una advertencia.
  </Step>

  <Step title="Para cada certificado de servicio">
    Para cada entrada en `certificates[]`:

    1. **Asegura una clave de servicio** en `key`. La genera (ECDSA P-256) si falta y la reutiliza si existe. Las claves nunca salen del host.
    2. **Comprueba el certificado existente** en `cert`. Si parsea, coincide con la clave y aún no entra en la ventana de `renew_before` (por defecto `720h`), registra `certificate skipped, not in renewal window` y continúa.
    3. **Construye un CSR** con exactamente los `dns_names` configurados.
    4. **Llama al broker.** Abre una conexión mTLS a `broker.url`, presentando `identity.cert` como cliente y confiando en `broker.server_ca_bundle` para el TLS del broker. Hace `POST /v1/certificates` con `{profile, csr_pem}`.
    5. **Valida el bundle.** Cuando el broker devuelve `cert_pem`, `chain_pem` y `fullchain_pem`, el agente verifica que la hoja coincide con la clave local y que tiene exactamente los DNS pedidos — nunca confía a ciegas en el broker.
    6. **Instala atómicamente.** Escribe `cert`, `chain` y `fullchain` en disco.
    7. **Recarga.** Si `reload_command` está definido, lo ejecuta con timeout `reload_timeout` (por defecto `30s`) y registra la salida.
  </Step>
</Steps>

## Qué hace el broker en `/v1/certificates`

Cuando recibe una solicitud de emisión:

1. **Autentica.** El TLS termina con `tls.RequireAndVerifyClientCert` contra `server.mtls.agent_ca_bundle`. La identidad es el CN del certificado cliente.
2. **Autoriza.** Busca la identidad en la política activa (`policy.path`), confirma que el `profile` solicitado aparece en `hosts.<key>.profiles` y valida los DNS del CSR contra los `dns_names` del perfil.
3. **Limita la tasa.** Aplica límites por identidad y por (identidad, perfil) según `rate_limits`.
4. **Sirve desde caché o emite.** Si hay un certificado cacheado para `(profile, huella del CSR)` fuera de la ventana de `renew_before` del perfil, lo devuelve. Si no, llama a ACME (Let's Encrypt por defecto) con el tipo de desafío del perfil, obtiene el certificado, lo guarda y lo devuelve.
5. **Audita.** Cada decisión — allow o deny, además de eventos de ciclo de vida del broker — se registra. Inspecciónalo con `certplane-broker ... audit tail`.

## Lo que nunca cruza la red

* **Claves privadas de servicio.** Siempre generadas y rotadas en el host que las usa.
* **Credenciales del proveedor DNS.** Se quedan en el broker. Los agentes no saben cómo se satisface el desafío ACME.
* **Claves de cuenta ACME.** Viven solo en el broker.

## A dónde ir después

* [Configurar el broker](/es/setup/broker) y [Configuración del broker](/es/configuration/broker)
* [Registro del agente](/es/setup/agent-enroll) y [Ejecutar el agente](/es/setup/agent-run)
* [Resumen de política](/es/policy/overview)
* [Guía de roles de Ansible](/es/guides/ansible)
