Commit Graph

31 Commits

Author SHA1 Message Date
Jacob Hoffman-Andrews 585319f247
issuance: remove profile hashes (#8118)
Part of #8039
2025-04-16 16:57:24 -07:00
Jacob Hoffman-Andrews 3ddaa6770f
ca: make orderID mandatory (#8119)
It was allowed to be empty for ACMEv1 requests, but those are long gone.

Also, move the IsAnyNilOrZero checks up to the RPC entry point.
2025-04-15 14:56:28 -07:00
Jacob Hoffman-Andrews d800055fe6
ca: Remove IssuePrecertificateResponse (#8115)
Instead, simply return DER bytes from `issuePrecertificate`, and accept
regular parameters to `issueCertificateForPrecertificate` (instead of a
proto message).

Also, move the lookup of the certificate profile up to
`IssueCertificate`, and pass the selected `*certProfileWithId` to both
`issuePrecertificate` and `issueCertificateForPrecertificate`.

Also, change `issueCertificateForPrecertificate` to just return DER, not
a `*corepb.Certificate` (of which most fields were already being
ignored).
2025-04-10 17:56:13 -07:00
Jacob Hoffman-Andrews 76de5bf561
ca: unexport IssuePrecertificate and IssueCertificateForPrecertificate (#8092)
These methods are still preserved as-is for now, and still take proto
messages as arguments. But they are not exported as RPCs. Refactoring
the arguments will be a followup PR.

Part of #8039
2025-04-03 16:11:39 -07:00
Jacob Hoffman-Andrews 692bd53ae5
ca: unsplit issuance flow (#8014)
Add a new RPC to the CA: `IssueCertificate` covers issuance of both the
precertificate and the final certificate. In between, it calls out to
the RA's new method `GetSCTs`.

The RA calls the new `CA.IssueCertificate` if the `UnsplitIssuance`
feature flag is true.

The RA had a metric that counted certificates by profile name and hash.
Since the RA doesn't receive a profile hash in the new flow, simply
record the total number of issuances.

Fixes https://github.com/letsencrypt/boulder/issues/7983
2025-02-24 11:37:17 -08:00
Aaron Gable a9e3ad1143
CA: Require RA to always provide profile name (#7991)
Deprecate the CA's DefaultCertificateProfileName config key, now that
default profile selection is being handled by the RA instead.

Part of https://github.com/letsencrypt/boulder/issues/7986
2025-02-11 13:10:29 -08:00
Aaron Gable 7b6935d223
Configure lints separately for each profile (#7636)
Move the two lint-configuration keys, LintConfig and IgnoreLints, from
the top-level CA.Issuance config stanza into each individual
CA.Issuance.CertProfiles stanza. This allows us to have
differently-configured lints for different profiles, to ensure that our
linting regime is as strict as possible.

Without this change, it would be necessary for us to ignore both the
"common name included" and the "no subject key id" lints at the
top-level, when in fact each of those warnings only triggers on one of
our two profiles.

Fixes https://github.com/letsencrypt/boulder/issues/7635
2024-08-01 10:01:46 -07:00
Aaron Gable cf8e5aa1b1
Use profile to determine backdate and validity (#7621)
One of our goals with profiles is to allow different profiles to have
different validity periods. While the profiles already had the ability
to enforce different maximum backdates and validities, the CA still had
separate global configuration for what the backdate and validity period
should actually be.

Move the computation of the notBefore and notAfter timestamps into the
issuance package, so that it can be based on the profile's configured
backdate and validity durations. Deprecate the global "backdate" and
"expiry" config fields, as they are no longer used. Finally, add more
validation for the profile's backdate and validity.

Part of https://github.com/letsencrypt/boulder/issues/7610
2024-07-25 13:47:51 -07:00
Phil Porada 9207669755
Deprecate ECDSAForAll feature and remove ECDSAAllowList (#7560)
`ECDSAForAll` feature is now enabled by default (due to it not being
referenced in any issuance path) and as a result the `ECDSAAllowlist`
has been deleted.

Fixes https://github.com/letsencrypt/boulder/issues/7535
2024-06-26 10:38:51 -04:00
Aaron Gable 602f3e4708
Fix reference bug in CA.noteSignError (#7534)
In the process of writing
https://github.com/letsencrypt/boulder/pull/7533 I discovered that the
method for detecting pkcs11.Error errors is broken: it attempts to
unwrap the returned error into a pointer-to-a-pointer type, which
doesn't work because only `pkcs11.Error` implements the Error interface,
while `*pkcs11.Error` does not.

Add a test which shows that the current noteSignError implementation is
broken. Then fix noteSignError and the two locations which duplicate
that code by removing the extra layer of indirection. And since the same
code exists in three locations, refactor how the caImpl, ocspImpl, and
crlImpl share metrics so that it only has to exist in one place.

A minimal reproduction case of this type of breakage can be seen here:
https://go.dev/play/p/qCLDQ1SFiWu
2024-06-07 15:34:02 -04:00
Aaron Gable b92581d620
Better compile-time type checking for gRPC server implementations (#7504)
Replaced our embeds of foopb.UnimplementedFooServer with
foopb.UnsafeFooServer. Per the grpc-go docs this reduces the "forwards
compatibility" of our implementations, but that is only a concern for
codebases that are implementing gRPC interfaces maintained by third
parties, and which want to be able to update those third-party
dependencies without updating their own implementations in lockstep.
Because we update our protos and our implementations simultaneously, we
can remove this safety net to replace runtime type checking with
compile-time type checking.

However, that replacement is not enough, because we never pass our
implementation objects to a function which asserts that they match a
specific interface. So this PR also replaces our reflect-based unittests
with idiomatic interface assertions. I do not view this as a perfect
solution, as it relies on people implementing new gRPC servers to add
this line, but it is no worse than the status quo which relied on people
adding the "TestImplementation" test.

Fixes https://github.com/letsencrypt/boulder/issues/7497
2024-05-28 09:26:29 -07:00
Aaron Gable 939ac1be8f
Add pkilint to CI via custom zlint (#7441)
Add a new "LintConfig" item to the CA's config, which can point to a
zlint configuration toml file. This allows lints to be configured, e.g.
to control the number of rounds of factorization performed by the Fermat
factorization lint.

Leverage this new config to create a new custom zlint which calls out to
a configured pkilint API endpoint. In config-next integration tests,
configure the lint to point at a new pkilint docker container.

This approach has three nice forward-looking features: we now have the
ability to configure any of our lints; it's easy to expand this
mechanism to lint CRLs when the pkilint API has support for that; and
it's easy to enable this new lint if we decide to stand up a pkilint
container in our production environment.

No production configuration changes are necessary at this time.

Fixes https://github.com/letsencrypt/boulder/issues/7430
2024-04-30 09:29:26 -07:00
Aaron Gable e05d47a10a
Replace explicit int loops with range-over-int (#7434)
This adopts modern Go syntax to reduce the chance of off-by-one errors
and remove unnecessary loop variable declarations.

Fixes https://github.com/letsencrypt/boulder/issues/7227
2024-04-22 10:34:51 -07:00
Aaron Gable 94d14689bf
Implement unpredictable issuance from similar intermediates (#7418)
Replace the CA's "useForRSA" and "useForECDSA" config keys with a single
"active" boolean. When the CA starts up, all active RSA issuers will be
used to issue precerts with RSA pubkeys, and all ECDSA issuers will be
used to issue precerts with ECDSA pubkeys (if the ECDSAForAll flag is
true; otherwise just those that are on the allow-list). All "inactive"
issuers can still issue OCSP responses, CRLs, and (notably) final
certificates.

Instead of using the "useForRSA" and "useForECDSA" flags, plus implicit
config ordering, to determine which issuer to use to handle a given
issuance, simply use the issuer's public key algorithm to determine
which issuances it should be handling. All implicit ordering
considerations are removed, because the "active" certificates now just
form a pool that is sampled from randomly.

To facilitate this, update some unit and integration tests to be more
flexible and try multiple potential issuing intermediates, particularly
when constructing OCSP requests.

For this change to be safe to deploy with no user-visible behavior
changes, the CA configs must contain:
- Exactly one RSA-keyed intermediate with "useForRSALeaves" set to true;
and
- Exactly one ECDSA-keyed intermediate with "useForECDSALeaves" set to
true.

If the configs contain more than one intermediate meeting one of the
bullets above, then randomized issuance will begin immediately.

Fixes https://github.com/letsencrypt/boulder/issues/7291
Fixes https://github.com/letsencrypt/boulder/issues/7290
2024-04-18 10:00:38 -07:00
Phil Porada c0ecabd244
CA: Run all CA package tests in parallel (#7438)
The CA tests don't share any state and create their own individual CA
implementations. We can safely run these tests in parallel within the CA
package to shave at least a second off of unit test runs at the expense
of additional CPU and memory usage.
2024-04-17 16:01:37 -07:00
Phil Porada 1e1f6ff254
CA: Load multiple certificate profiles (#7325)
This change introduces a new config key `certProfiles` which contains a
map of `profiles`. Only one of `profile` or `certProfiles` should be
used, because configuring both will result in the CA erroring and
shutting down. Further, the singular `profile` is now
[deprecated](https://github.com/letsencrypt/boulder/issues/7414).

The CA pre-computes several maps at startup; 
* A human-readable name to a `*issuance.Profile` which is referred to as
"name".
* A SHA-256 sum over the entire contents of the given profile to the
`*issuance.Profile`. We'll refer to this as "hash".

Internally, CA methods no longer pass an `*issuance.Profile`, instead
they pass a structure containing maps of certificate profile
identifiers. To determine the default profile used by the CA, a new
config field `defaultCertificateProfileName` has been added to the
Issuance struct. Absence of `defaultCertificateProfileName` will cause
the CA to use the default value of `defaultBoulderCertificateProfile`
such as for the the deprecated `profile`. The key for each given
certificate profile will be used as the "name". Duplicate names or
hashes will cause the CA to error during initialization and shutdown.

When the RA calls `ra.CA.IssuePrecertificate`, it will pass an arbitrary
certificate profile name to the CA triggering the CA to lookup if the
name exists in its internal mapping. The RA maintains no state or
knowledge of configured certificate profiles and relies on the CA to
provide this information. If the name exists in the CA's map, it will
return the hash along with the precertificate bytes in a
`capb.IssuePrecertificateResponse`. The RA will then call
`ra.CA.IssueCertificateForPrecertificate` with that same hash. The CA
will lookup the hash to determine if it exists in its map, and if so
will continue on with certificate issuance.

Precertificate and certificate issuance audit logs will now include the
certificate profile name and hex representation of the hash that they
were issued with.

Fixes https://github.com/letsencrypt/boulder/issues/6966

There are no required config or SQL changes.
2024-04-08 12:52:46 -04:00
Phil Porada aece244f3b
test: Use more //test/hierarchy/ key material in tests (#7318)
The `//ca/ca_test.go` `setup` function will now create issuers that each
have a unique private key from `//test/hierarchy/`, rather than multiple
issuers sharing a private key. This was spotted while reviewing an [OCSP
test](10e894a172/ca/ocsp_test.go (L53-L87)).
Some now unnecessary key material has been deleted from `//test/`.

Fixes https://github.com/letsencrypt/boulder/issues/7304
2024-02-09 14:39:07 -05:00
Aaron Gable af2c1a5963
Separate issuance.Profile out from issuance.Issuer (#7285)
Remove the Profile field from issuance.Issuer, to reflect the fact that
profiles are in fact independent pieces of configuration which can be
shared across (and are configured independently of) multiple issuers.

Move the IssuerURL, OCSPUrl, and CRLURL fields from issuance.Profile to
issuance.Issuer, since they reflect fundamental attributes of the
issuer, rather than attributes of a particular profile. This also
reflects the location at which those values are configured, in
issuance.IssuerConfig.

All other changes are fallout from the above: adding a Profile argument
to various methods in the issuance and linting packages, adding a
profile field to the caImpl struct, etc. This change paves the way for
two future changes: moving OCSP and CRL creation into the issuance
package, and supporting multiple simultaneous profiles that the CA can
select between.

Part of https://github.com/letsencrypt/boulder/issues/7159
Part of https://github.com/letsencrypt/boulder/issues/6316
Part of https://github.com/letsencrypt/boulder/issues/6966
2024-02-06 17:06:56 -08:00
Aaron Gable ab6e023b6f
Simplify issuance.NameID and how it is used (#7260)
Rename "IssuerNameID" to just "NameID". Similarly rename the standalone
functions which compute it to better describe their function. Add a
.NameID() directly to issuance.Issuer, so that callers in other packages
don't have to directly access the .Cert member of an Issuer. Finally,
rearrange the code in issuance.go to be sensibly grouped as concerning
NameIDs, Certificates, or Issuers, rather than all mixed up between the
three.

Fixes https://github.com/letsencrypt/boulder/issues/5152
2024-01-17 12:55:56 -08:00
Aaron Gable a9a87cd4a8
Remove fallbacks from IssuerNameID to IssuerID (#7259)
The last rows using the old-style IssuerID were written to the database
in late 2021. Those rows have long since aged out -- we no longer serve
certificates or revocation information for them -- so we can remove the
code which handles those old-style IDs. This allows for some nice
simplifications in the CA's ocspImpl and in the Issuance package, which
will be useful for further reorganization of the CA and issuance
packages.

Fixes https://github.com/letsencrypt/boulder/issues/5152
2024-01-12 14:03:49 -08:00
Jacob Hoffman-Andrews 725f190c01
ca: remove orphan queue code (#7025)
The `orphanQueueDir` config field is no longer used anywhere.

Fixes #6551
2023-08-02 16:04:28 -07:00
Aaron Gable 45329c9472
Deprecate ROCSPStage7 flag (#6804)
Deprecate the ROCSPStage7 feature flag, which caused the RA and CA to
stop generating OCSP responses when issuing new certs and when revoking
certs. (That functionality is now handled just-in-time by the
ocsp-responder.) Delete the old OCSP-generating codepaths from the RA
and CA. Remove the CA's internal reference to an OCSP implementation,
because it no longer needs it.

Additionally, remove the SA's "Issuers" config field, which was never
used.

Fixes #6285
2023-04-12 17:03:06 -07:00
Aaron Gable 9262ca6e3f
Add grpc implementation tests to all services (#6782)
As a follow-up to #6780, add the same style of implementation test to
all of our other gRPC services. This was not included in that PR just to
keep it small and single-purpose.
2023-03-31 09:52:26 -07:00
Aaron Gable 427bced0cd
Remove OCSP and CRL methods from CA gRPC service (#6474)
Remove the GenerateOCSP and GenerateCRL methods from the
CertificateAuthority gRPC service. These methods are no longer called by
any clients; all clients use their respective OCSPGenerator and
CRLGenerator gRPC services instead.

In addition, remove the CRLGeneratorServer field from the caImpl, as it
no longer needs it to serve as a backing implementation for the
GenerateCRL pass-through method. Unfortunately, we can't remove the
OCSPGeneratorServer field until after ROCSPStage7 is complete, and the
CA is no longer generating an OCSP response during initial certificate
issuance.

Part of #6448
2023-02-23 14:42:14 -08:00
Nina cdf1d321a5
ocsp: log revocation reason code (#6228)
In the CA, rather than logging just the revocation status (0 for Good,
1 for Revoked), begin logging the integer revocation reason (0 for
Unspecified, 1 for KeyCompromise, etc). For OCSP responses with the Good
status, log an underscore ("_") indicating that the revocation reason is
inapplicable.

This brings the OCSP audit logging in line with the new CRL logging,
which logs the reason for each serial included in a CRL.

Fixes #6214
2022-08-01 12:53:17 -07:00
Nina 6986f0d756
ca: avoid ocsp.ResponseStatus (#6213) 2022-07-05 15:43:06 -07:00
Aaron Gable e13918b50e
CA: Add GenerateCRL gRPC method (#6187)
Add a new CA gRPC method named `GenerateCRL`. In the
style of the existing `GenerateOCSP` method, this new endpoint
is implemented as a separate service, for which the CA binary
spins up an additional gRPC service.

This method uses gRPC streaming for both its input and output.
For input, the stream must contain exactly one metadata message
identifying the crl number, issuer, and timestamp, and then any
number of messages identifying a single certificate which should
be included in the CRL. For output, it simply streams chunks of
bytes.

Fixes #6161
2022-06-29 11:03:12 -07:00
Aaron Gable 7bf854fe03
Move OCSP gRPC service to separate file and struct (#5402)
Create a new `ocspImpl` struct which satisfies the interface required
by the `OCSPGenerator` gRPC service. Move the `GenerateOCSP`
method from the `certificateAuthorityImpl` to this new type. To support
existing gRPC clients, keep a reference to the new OCSP service in
the CA impl, and maintain a pass-through `GenerateOCSP` method.
Simplify some of the CA setup code, and make the CA implementation
non-exported because it doesn't need to be.

In order to maintain our existing signature and sign error metrics,
they now need to be initialized outside the CA and OCSP constructors.
This complicates the tests slightly, but seems like a worthwhile
tradeoff.

Fixes #5226
Fixes #5086
2021-04-29 14:20:39 -07:00
Andrew Gabbitas a718a9349d
Add waiting mock log writer (#5359)
Add a mock log buffer that is able to wait for a regex match in the
log buffer or timeout and error.

Fixes #5310
2021-04-01 10:53:21 -07:00
Jacob Hoffman-Andrews 9464d025d1
Fix OCSP log queue blocking when maxLogLen = 0. (#5230)
Move responsibility for handling the default path (maxLogLen = 0)
from the ocspLogQueue component to CertificateAuthorityImpl. Now the
ocspLogQueue isn't constructed at all unless we configure it to be used.

Also, remove buffer from OCSP audit log chan. The bug this fixes was
hidden by the large buffer, and on reconsideration the large buffer was
unnecessary.

Verified that with the buffer removed, the integration test fails. Then
adding the fixes to the maxLogLen = 0 case fixes the integration test.

Fixes #5228
2021-01-15 11:32:00 -08:00
Jacob Hoffman-Andrews 8b9145838d
Add logging of OCSP generation events (#5223)
This adds a new component to the CA, ocspLogQueue, which batches up
OCSP generation events for audit logging. It will log accumulated
events when it reaches a certain line length, or when a maximum amount
of times has passed.
2021-01-12 15:31:49 -08:00