boulder

repository·main·Indexed 26 days ago

https://github.com/letsencrypt/boulder

An implementation of an ACME-based Certificate Authority (CA) that powers Let's Encrypt. It is a modular system of specialized components communicating via gRPC for automated certificate issuance and validation. The project includes the boulder-observer daemon for Prometheus-based monitoring of DNS, HTTP, CRL, AIA, TLS, and CCADB, as well as a ceremony tool for performing CA-specific key and certificate ceremonies using HSMs via PKCS#11.

Tokens
35.3K
Snippets
52
Records
216
Agent score
91%

What's inside boulder

  1. Overview of Boulder components

    main

    Boulder is a modular ACME-based Certificate Authority (CA) composed of several specialized components that communicate via gRPC. This separation allows for different security contexts for each component.

    Main Components:

    1. Web Front Ends (WFE): One per API version; handles external requests.
    2. Registration Authority (RA): Manages account and order logic.
    3. Validation Authority (VA): Handles domain validation challenges.
    4. Certificate Authority (CA): Issues certificates based on RA instructions.
    5. Storage Authority (SA): Maintains persistent state (typically using MariaDB).
    6. Publisher: Handles certificate publication.
    7. CRL Updater: Manages Certificate Revocation Lists.

    Core Objects: The system logic revolves around five ACME resource types: accounts, authorizations, challenges, orders, and certificates.

  2. Understand the vschema directory structure

    main
    The sa/vschema/ directory contains vschema files for each of the project's keyspaces. These files are used by Vitess to define the schema for different keyspaces. At runtime within the bvitess container, these files are merged with the .sql files from sa/db/ into a single combined directory. This combined directory is then passed to vttestserver using the --schema-dir flag.
  3. Understand the Multi-VA service architecture

    main

    The Multi-VA implementation consists of two distinct software components that share the same underlying va package:

    • boulder-va: The primary validation service.
    • remoteva: The remote validation service.

    Both services use the same gRPC interface to perform validations. The boulder-ra (Registration Authority) uses this same RPC interface to request primary validations, just as a primary VA uses it to request confirmation validations from a remote VA.

  4. Understand the Boulder rate limit token-bucket model

    main

    Boulder uses a token-bucket model for rate limiting. Each limit is represented by a bucket that holds tokens.

    • burst: The maximum capacity of the bucket. This defines how many requests can be made in a single burst before the bucket is empty.
    • count: The number of tokens added to the bucket per period.
    • period: The duration over which count tokens are added.
    • Steady-state rate: Once a burst is exhausted, a client can make requests at a rate of one token every (period / count) duration.
  5. Understand Boulder's ACME specification divergences

    main
    Boulder implements the ACME specification (RFC 8555) but diverges from it in several specific areas. When building an ACME client to interact with Boulder (available at https://acme-v02.api.letsencrypt.org/directory), be aware of the following implementation differences:
  6. Use the nameid tool to link CA and end-entity certificates

    main

    The nameid tool computes a statistically-unique small ID from certificates to link them into a validation chain. This ID is a truncated hash over the issuer Subject Name bytes.

    Important: The tool should only be used on issuer certificates (where the IsCA boolean is true in the //crypto/x509 Certificate struct).

  7. Understand CRL shard assignment and storage

    main

    Boulder generates sharded Certificate Revocation Lists (CRLs) for each issuer.

    • Shard Selection: Shards are assigned at issuance time. The shard index is determined by taking the low bytes of the certificate's serial number modulo the total number of shards produced by the issuer. This shard index is baked into the certificate's CRLDistributionPoints extension.
    • Storage Path: CRLs are uploaded to an S3-compatible store using the pattern <issuerID>/<shard>.crl, where <issuerID> is a unique integer derived from hashing the encoded bytes of the issuer's Subject.
    • Revocation Data: Revocation status is tracked in two tables: certificateStatus and revokedCertificates. The revokedCertificates table is the scalable mechanism used for CRL generation.
  8. Manage dependencies and vendorizing

    main

    Boulder uses Go modules and vendors all dependencies.

    Adding a dependency:

    1. Add the import statement to your .go file.
    2. Run go build to update go.mod.
    3. Run go mod vendor && git add vendor/ to save the copy in the vendor folder.
    4. Note: If the dependency version is not a tagged release, you must run its tests and include a comment in your PR indicating that the tests passed (including the command used).

    Upgrading a dependency:

    1. Use go get <dependency> (avoid go get -u to prevent unexpected transitive updates).
    2. Run go mod vendor && git add vendor/ to update the vendor directory.
    3. If an update introduces new transitive dependencies from a different repository, explain the reason in the PR description.
    go get <dependency>
    go mod vendor && git add vendor/
  9. Handle optional Timestamps in Protobuf

    main

    Timestamps in protocol buffers must use timestamppb.Timestamp.

    Rules:

    • No Zero Values: Timestamps must never contain their zero value (timestamp.AsTime().IsZero()).
    • Express Absence: When a timestamp is optional, express its absence by omitting the field entirely rather than sending a zero value.
    • Validation: Senders must check that timestamps are non-zero before sending. Receivers must check that timestamps are non-zero before accepting. Use core.IsAnyNilOrZero to check these cases.
  10. Format Certificate Signing Requests (CSR) for Boulder

    main

    When submitting a CSR to Boulder, ensure that all requested domains are specified in the subjectAltName extension.

    Boulder will reject a CSR if a domain specified in the commonName is not also present in the subjectAltName. While the RFC allows identifiers to appear in the commonName, Boulder requires the subjectAltName extension for all domains to align with modern CA/B Forum deprecation of commonName usage.

  11. Configure Multi-Perspective Validation (Multi-VA) in Development

    main

    Boulder supports multi-perspective validation to increase resilience against network hijacks and BGP attacks. In a development environment using Docker, you can enable a Multi-VA setup by changing the BOULDER_CONFIG_DIR environment variable in your docker-compose.yml to test/config-next instead of the default test/config.

    This configuration sets up:

    • Two primary VA instances (load balanced).
    • Two remote VA instances (each primary VA queries both remotes for matching validations).

    Note: In this development mode, all instances run on a single host.