Documentation
¶
Overview ¶
Package enroll реализует bootstrap-энроллмент агента (Этап 3): агент сам генерит ключевую пару и CSR, получает по одноразовому токену подписанный сервером сертификат (CN=device_id ставит сервер, ADR-1) и раскладывает mTLS-материал на диск. Контракт — docs/enrollment.md (REST POST /api/v1/enroll).
Приватный ключ НИКОГДА не покидает устройство: сервер получает только CSR (публичный ключ). Канал энроллмента — server-auth TLS, доверие к серверу до получения CA обеспечивается CA-бандлом из установочного пакета (пин), запрос аутентифицируется одноразовым токеном.
Index ¶
- Variables
- func FetchPinnedCA(caURL, caSHA256 string) ([]byte, error)
- func LeafSignedByCA(leaf *x509.Certificate, caCerts []*x509.Certificate) error
- func LoadCABundle(caFile, caURL, caSHA256 string) ([]byte, error)
- func ParseCACerts(pemBytes []byte) ([]*x509.Certificate, error)
- func Run(ctx context.Context, req Request, log *slog.Logger) (string, error)
- func ValidateCABundle(pemBytes []byte) ([]*x509.Certificate, error)
- type Request
Constants ¶
This section is empty.
Variables ¶
var ErrCAPinMismatch = errors.New("CA-бандл не прошёл пин-проверку")
ErrCAPinMismatch — бандл не сошёлся с -ca-sha256. Это не «сеть моргнула»: либо MITM, либо пин в параметрах установщика протух (CA переиздали, команду не обновили). Деградировать на CA с диска по этой ошибке нельзя.
var ErrNoCASource = errors.New("для энроллмента нужен CA-бандл: задайте -ca <файл> или -ca-url <url>")
ErrNoCASource — источника CA нет вовсе: ни файла -ca на диске, ни -ca-url. Отдельная ошибка, чтобы вызывающий отличал «проверять нечем» от «проверили и не сошлось» (cmd/agent на первом сохраняет идемпотентность, на втором падает).
Functions ¶
func FetchPinnedCA ¶
FetchPinnedCA скачивает CA-бандл по URL и сверяет с пином. В отличие от LoadCABundle НЕ смотрит на диск: только так видно переиздание CA на сервере — лежащий на диске ca.crt остался бы старым и «подтвердил» бы старую идентичность.
func LeafSignedByCA ¶
func LeafSignedByCA(leaf *x509.Certificate, caCerts []*x509.Certificate) error
LeafSignedByCA — ядро проверки «этот leaf выписан этим CA»: подпись + EKU, без часов. Всё «почему без часов» — в доке certChainsToCA выше; коротко: любой выбор CurrentTime ломается (time.Now() — на съехавших назад часах, leaf.NotBefore — на CA моложе минуты).
Экспортировано, потому что ровно та же проверка нужна cmd/agent для УЖЕ УСТАНОВЛЕННОЙ идентичности (reusableIdentity): вопрос там тот же, и второй реализации у него быть не должно — своя копия уже разошлась с этой и принесла ту самую ошибку с часами.
func LoadCABundle ¶
LoadCABundle — экспорт loadCABundle для cmd/agent: тем же бандлом, которым Run пинит enroll-запрос, проверяется и издатель уже лежащей на диске идентичности (иначе агент после переиздания CA молча оставил бы чужой серт).
func ParseCACerts ¶
func ParseCACerts(pemBytes []byte) ([]*x509.Certificate, error)
ParseCACerts разбирает CA-бандл в сертификаты БЕЗ проверки сроков: единственный потребитель — сверка издателя (LeafSignedByCA), которой часы противопоказаны. Срок годности CA проверяет validateCABundle на пути энроллмента.
func ValidateCABundle ¶
func ValidateCABundle(pemBytes []byte) ([]*x509.Certificate, error)
ValidateCABundle — экспорт validateCABundle для cmd/agent: CA, дотянутый по -ca-url на reused-пути (relocateForService), проходит ту же проверку пригодности («это вообще CA?»), что и бандл на свежем энроллменте. Пин отвечает только за целостность байт — лист-сертификат вместо CA он не поймает.
Types ¶
type Request ¶
type Request struct {
EnrollURL string // полный URL эндпоинта, напр. https://host:8081/api/v1/enroll
Token string // одноразовый enrollment-токен (UUID v4)
CAFile string // CA-бандл из пакета: пин TLS enroll-эндпоинта
CAURL string // откуда скачать CA-бандл, если CAFile нет на диске (TOFU)
CASHA256 string // ожидаемый hex sha256 CA-бандла: пин против MITM на TOFU-шаге
CertOut string // куда записать выданный сертификат (agent.crt)
KeyOut string // куда записать локально сгенерённый ключ (agent.key)
CAOut string // куда записать CA для рантайма (ca.crt)
// ReleaseKeyOut — куда записать base64 release-pubkey из enroll-ответа (для
// самообновления универсального агента без вшитого ключа). Пусто — не пишем.
ReleaseKeyOut string
Hostname string // справочно для UI
OS string
Arch string
// HTTPClient — для тестов; в проде nil → клиент строится с пином CAFile.
HTTPClient *http.Client
}
Request — параметры энроллмента.