Commit Graph

710 Commits

Author SHA1 Message Date
Aaron Gable f089aa5d5f
SA.GetOrder: conduct queries inside a transaction (#6541)
The SA's GetOrder method issues four separate database queries:
- get the Order object itself
- get the list of Names associated with it
- get the list of Authorization IDs associated with it
- get the contents of those Authorizations themselves

These four queries can hit different database replicas with different
amounts of replication lag, and therefore different views of the
universe. This can result in inconsistent results, such as the Order
existing, but not having any Authorization IDs associated with it.

Conduct these four queries all within a single transaction, to ensure
they all hit a single read-replica with a consistent view of the world.

Fixes #6540
2022-12-05 12:09:57 -08:00
Aaron Gable d8d5a030f4
SA: Remove NewOrder and NewAuthorizations2 (#6536)
Delete the NewOrder and NewAuthorizations2 methods from the SA's gRPC
interface. These methods have been replaced by the unified
NewOrderAndAuthzs method, which performs both sets of insertions in a
single transaction.

Also update the SA and RA unittests to not rely on these methods for
setting up test data that other functions-under-test rely on. In most
cases, replace calls to NewOrder with calls to NewOrderAndAuthzs. In the
SA tests specifically, replace calls to NewAuthorizations2 with a
streamlined helper function that simply does the single necessary
database insert.

Fixes #6510
Fixes #5816
2022-12-02 14:34:35 -08:00
Aaron Gable ba34ac6b6e
Use read-only SA clients in wfe, ocsp, and crl (#6484)
In the WFE, ocsp-responder, and crl-updater, switch from using
StorageAuthorityClients to StorageAuthorityReadOnlyClients. This ensures
that these services cannot call methods which write to our database.

Fixes #6454
2022-12-02 13:48:28 -08:00
Aaron Gable b7e4e9d0ce
SA: Remove AddCertificate's unused return value (#6532)
The `digest` value in AddCertificate's response message is never used by
any callers. Remove it, replacing the whole response message with
google.protobuf.Empty, to mirror the AddPrecertificate method.

This swap is safe, because message names are not sent on the network,
and empty message fields are omitted from the wire format entirely, so
sending the predefined Empty message is identical to sending an empty
AddCertificateResponse message. Since no client is inspecting the
response to access the digest field, sending an empty response will not
break any clients.

Fixes #6498
2022-11-30 13:00:56 -08:00
J.C. Jones 6805c39580
Fix typo for omitZero in database.go from PR #6492 (#6515)
We have a new method, omitZero, which is to allow `max_statement_time`
and `long_query_time` to be zeroed out, but copy/paste error left
`long_query_time` out. Fix it.
2022-11-17 13:27:57 -08:00
Aaron Gable 992ae61439
SA.NewOrder: Get order status inside transaction (#6512)
The SA's NewOrder and NewOrderAndAuthzs methods both write new rows (the
order itself, new authorizations, and new OrderToAuthz relations) to the
database, and then quickly turn around and query the database for a
bunch of authz rows to compute the status of the new order. This is
necessary because many orders are created already referencing existing
authorizations, and the state of those authorizations is not known at
order creation time, but does affect the order's status.

Due to replication lag, it can cause issues if the database writes go to
the primary database, but the follow-up read goes to a read-only
database replica which may be lagging slightly. To prevent this issue,
conduct the reads on the same transaction as the writes.

Fixes #6511
2022-11-16 16:53:23 -08:00
Samantha 76b2ec0702
SA: Standardize methods which use COUNT queries (#6505)
- Replace `-1` in return values with `0`. No callers were depending on
`-1`.
- Replace `count(` with `COUNT(` for the sake of readability.
- Replace `COUNT(1)` with `COUNT(*)` (https://mariadb.com/kb/en/count).
Both
  versions provide identical outputs but let's standardize on the docs.

Fixes #6494
2022-11-14 18:10:32 -08:00
Aaron Gable 4f473edfa8
Deprecate 10 feature flags (#6502)
Deprecate these feature flags, which are consistently set in both prod
and staging and which we do not expect to change the value of ever
again:
- AllowReRevocation
- AllowV1Registration
- CheckFailedAuthorizationsFirst
- FasterNewOrdersRateLimit
- GetAuthzReadOnly
- GetAuthzUseIndex
- MozRevocationReasons
- RejectDuplicateCSRExtensions
- RestrictRSAKeySizes
- SHA1CSRs

Move each feature flag to the "deprecated" section of features.go.
Remove all references to these feature flags from Boulder application
code, and make the code they were guarding the only path. Deduplicate
tests which were testing both the feature-enabled and feature-disabled
code paths. Remove the flags from all config-next JSON configs (but
leave them in config ones until they're fully deleted, not just
deprecated). Finally, replace a few testdata CSRs used in CA tests,
because they had SHA1WithRSAEncryption signatures that are now rejected.

Fixes #5171 
Fixes #6476
Part of #5997
2022-11-14 09:24:50 -08:00
Aaron Gable 9e67423110
Create new StorageAuthorityReadOnly gRPC service (#6483)
Create a new gRPC service named StorageAuthorityReadOnly which only
exposes a read-only subset of the existing StorageAuthority service's
methods.

Implement this by splitting the existing SA in half, and having the
read-write half embed and wrap an instance of the read-only half.
Unfortunately, many of our tests use exported read-write methods as part
of their test setup, so the tests are all being performed against the
read-write struct, but they are exercising the same code as the
read-only implementation exposes.

Expose this new service at the SA on the same port as the existing
service, but with (in config-next) different sets of allowed clients. In
the future, read-only clients will be removed from the read-write
service's set of allowed clients.

Part of #6454
2022-11-09 11:09:12 -08:00
Jacob Hoffman-Andrews ee1afbb988
SA: Enable overriding max_statement_time in DSN (#6492)
Also sql_mode and long_query_time.
2022-11-07 15:42:58 -08:00
Samantha 6838a2cf0b
RA: Return retry-after when Certificates per Registered Domain is exceeded (#6470)
Have the database query return timestamps for when certificates
were issued for certain names. Use that information to compute
when the next time that name will be eligible for issuance again.
Include that timestamp in the error message and a Retry-After
HTTP header.

Fixes #6465
2022-11-01 11:33:19 -07:00
Aaron Gable 30d8f19895
Deprecate ROCSP Stage 1, 2, and 3 flags (#6460)
These flags are set in both staging and prod. Deprecate them, make
all code gated behind them the only path, and delete code (multi_source)
which was only accessible when these flags were not set.

Part of #6285
2022-10-21 14:58:34 -07:00
Aaron Gable 941d7bfbe4
SA: Add GetLastExpiry gRPC method (#6443)
This method simply returns the greatest notAfter timestamp in
the certificateStatus table. This will be used by the crl-updater
to ensure that it includes all unexpired certificates in its CRLs,
rather than only those which happen to fall within its configured
bounds.

Part of #6438
2022-10-18 13:06:17 -07:00
Matthew McPherrin 6874d909f2
Enable go vet printf-auditing our logger (#6421)
Explicitly inform go vet about the names of our logging methods
which should be checked in the same way as fmt.Printf is. Although
go vet can often find such functions on its own, it can't find these
ones because log.Logger is an interface, not a struct.

In addition, fix several format string mistakes caught by go vet.
2022-09-30 16:37:53 -07:00
Samantha 78ea1d2c9d
SA: Use separate schema for incidents tables (#6350)
- Move incidents tables from `boulder_sa` to `incidents_sa` (added in #6344)
- Grant read perms for all tables in `incidents_sa`
- Modify unit tests to account for new schema and grants
- Add database cleaning func for `boulder_sa`
- Adjust cleanup funcs to omit `sql-migrate` tables instead of `goose`

Resolves #6328
2022-09-09 15:17:14 -07:00
Samantha bc1bf0fde4
test: Support multiple database schemas (#6344)
In dev docker we've always used a single schema (`boulder_sa`), with two
environments (`test` and `integration`) making for a combined total of two
databases sharing the same users and schema (e.g. `boulder_sa_test` and
`boulder_sa_integration`). There are also two versions of this schema. `db` and
`db-next`. The former is the schema as it should exist in production and the
latter is everything from `db` with some un-deployed schema changes. This change
adds support for additional schemas with the same aforementioned environments
and versions.

- Add support for additional schemas in `test/create_db.sh` and sa/migrations.sh
- Add new schema `incidents_sa` with its own users
- Replace `bitbucket.org/liamstask/goose/` with `github.com/rubenv/sql-migrate`

Part of #6328
2022-09-07 14:59:08 -07:00
Samantha cba5813019
WFE: Implement ARI for certificates impacted by incidents (#6313)
Suggest that subscribers with certificates impacted by an ongoing revocation
incident renew immediately.

- Make SA method `IncidentsForSerial` a callable RPC

Resolves #6282
2022-08-31 11:53:12 -07:00
Aaron Gable 0340b574d9
Add unparam linter to CI (#6312)
Enable the "unparam" linter, which checks for unused function
parameters, unused function return values, and parameters and
return values that always have the same value every time they
are used.

In addition, fix many instances where the unparam linter complains
about our existing codebase. Remove error return values from a
number of functions that never return an error, remove or use
context and test parameters that were previously unused, and
simplify a number of (mostly test-only) functions that always take the
same value for their parameter. Most notably, remove the ability to
customize the RSA Public Exponent from the ceremony tooling,
since it should always be 65537 anyway.

Fixes #6104
2022-08-23 12:37:24 -07:00
Aaron Gable 4ad66729d2
Tests: use reflect.IsNil() to avoid boxed nil issues (#6305)
Add a new `test.AssertNil()` helper to facilitate asserting that a given
unit test result is a non-boxed nil. Update `test.AssertNotNil()` to use
the reflect package's `.IsNil()` method to catch boxed nils.

In Go, variables whose type is constrained to be an interface type (e.g.
a function parameter which takes an interface, or the return value of a
function which returns `error`, itself an interface type) should
actually be thought of as a (T, V) tuple, where T is their underlying
concrete type and V is their underlying value. Thus, there are two ways
for such a variable to be nil-like: it can be truly nil where T=nil and
V is uninitialized, or it can be a "boxed nil" where T is a nillable
type such as a pointer or a slice and V=nil.

Unfortunately, only the former of these is == nil. The latter is the
cause of frequent bugs, programmer frustration, a whole entry in the Go
FAQ, and considerable design effort to remove from Go 2.

Therefore these two test helpers both call `t.Fatal()` when passed a
boxed nil. We want to avoid passing around boxed nils whenever possible,
and having our tests fail whenever we do is a good way to enforce good
nil hygiene.

Fixes #3279
2022-08-19 14:47:34 -07:00
Aaron Gable 09195e6804
ocsp-responder: get minimal status info from SA (#6293)
Add a new `GetRevocationStatus` gRPC method to the SA which retrieves
only the subset of the certificate status metadata relevant to
revocation, namely whether the certificate has been revoked, when it was
revoked, and the revocation reason. Notably, this method is our first
use of the `goog.protobuf.Timestamp` type in a message, which is more
ergonomic and less prone to errors than using unix nanoseconds.

Use this new method in ocsp-responder's checked_redis_source, to avoid
having to send many other pieces of metadata and the full ocsp response
bytes over the network. It provides all the information necessary to
determine if the response from Redis is up-to-date.

Within the checked_redis_source, use this new method in two different
ways: if only a database connection is configured (as is the case today)
then get this information directly from the db; if a gRPC connection to
the SA is available then prefer that instead. This may make requests
slower, but will allow us to remove database access from the hosts which
run the ocsp-responder today, simplifying our network.

The new behavior consists of two pieces, each locked behind a config
gate:
- Performing the smaller database query is only enabled if the
  ocsp-responder has the `ROCSPStage3` feature flag enabled.
- Talking to the SA rather than the database directly is only enabled if
  the ocsp-responder has an `saService` gRPC stanza in its config.

Fixes #6274
2022-08-16 16:37:24 -07:00
Aaron Gable dd5968f02d
Fix merge conflict in sa_test.go (#6288)
GitHub doesn't auto-rebase changes before merging, and doesn't re-run
tests against the current HEAD of the target branch before merging, so
it didn't catch that all uses of ioutil had been removed in #6286 while
a new usage was added in #6284. Replace the new usage of ioutil with
the appropriate function from the os package instead.
2022-08-10 16:44:37 -07:00
Aaron Gable 3a12177eab
ROCSP Stage 6: Never write OCSP responses to DB (#6284)
Create a new `ROCSPStage6` feature flag which affects the behavior of
the SA. When enabled, this flag causes the `AddPrecertificate`,
`RevokeCertificate`, and `UpdateRevokedCertificate` methods to ignore
the OCSP response bytes provided by their caller. They will no longer
error out if those bytes are missing, and if the bytes are present they
will still not be written to the database.

This allows us to, in the future, cause the RA and CA to stop generating
those OCSP responses entirely, and stop providing them to the SA,
without causing any errors when we do.

Part of #6079
2022-08-10 15:31:26 -07:00
Aaron Gable d1b211ec5a
Start testing on go1.19 (#6227)
Run the Boulder unit and integration tests with go1.19.

In addition, make a few small changes to allow both sets of
tests to run side-by-side. Mark a few tests, including our lints
and generate checks, as go1.18-only. Reformat a few doc
comments, particularly lists, to abide by go1.19's stricter gofmt.

Causes #6275
2022-08-10 15:30:43 -07:00
Aaron Gable 9c197e1f43
Use io and os instead of deprecated ioutil (#6286)
The iotuil package has been deprecated since go1.16; the various
functions it provided now exist in the os and io packages. Replace all
instances of ioutil with either io or os, as appropriate.
2022-08-10 13:30:17 -07:00
Samantha 1464c34938
RA: Implement leaky bucket for duplicate certificate limit (#6262)
- Modify `ra.checkCertificatesPerFQDNSetLimit()` to use a leaky bucket algorithm
- Return issuance timestamps from `sa.FQDNSetTimestampsForWindow()` in descending order

Resolves #6154
2022-07-29 17:39:31 -07:00
Samantha fca728087f
RA: Use sa.FQDNSetTimestampsForWindow for rate limit (#6225)
Fixes #6221
2022-07-28 15:04:51 -07:00
Aaron Gable 27de4befb9
Don't panic on duplicate db metrics (#6247)
Use `prometheus.Register` instead of `.MustRegister` when
setting up database metrics. This allows us to capture and
return up the call-chain any errors encountered during metric
initialization. While this does not actually help mitigate or
prevent any future duplicate-metrics errors, it will make them
easier to debug by surfacing them as well-formed errors rather
than simply stack-traces.

Fixes #6150
2022-07-23 11:11:15 -07:00
Nina ac0752ea53
sa: remove rocsp code (#6235)
Fixes #6208
2022-07-18 13:31:26 -07:00
Jacob Hoffman-Andrews 29724cb0b7
ocsp/responder: update Redis source to use live signing (#6207)
This enables ocsp-responder to talk to the RA and request freshly signed
OCSP responses.

ocsp/responder/redis_source is moved to ocsp/responder/redis/redis_source.go
and significantly modified. Instead of assuming a response is always available
in Redis, it wraps a live-signing source. When a response is not available,
it attempts a live signing.

If live signing succeeds, the Redis responder returns the result right away
and attempts to write a copy to Redis on a goroutine using a background
context.

To make things more efficient, I eliminate an unneeded ocsp.ParseResponse
from the storage path. And I factored out a FakeResponse helper to make
the unittests more manageable.

Commits should be reviewable one-by-one.

Fixes #6191
2022-07-18 10:47:14 -07:00
Samantha cfc16cd3ba
SA: Add FQDNSetIssuanceForWindow method (#6220)
Part of #6221
Part of #6154
2022-07-07 15:09:33 -07:00
Jacob Hoffman-Andrews 18b5194f2e
rocsp: remove Metadata (#6206)
The metadata values were planned to be used for scanning Redis in
ocsp-updater. Since we won't do that, remove it. Happily, this also
allows us to get rid of shortIssuerId.

Removing the issuer check in rocsp_sa.go uncovered a "boxed nil" problem:
SA was doing a nil check against an interface field that in practice was
never nil (because it was promoted from a concrete type at construction
time). So we would always hit the ROCSP path. But one of the first steps
in that path was looking up an issuer ID. Since `test/config` never
had the issuers set, we would look up the issuer ID, not find it, and
return an error before we attempted to call storeResponse. To fix this,
I made `NewSQLStorageAuthority` take a concrete `*rocsp.WritingClient`
instead of an interface, and check for nil before assigning it to an
internal interface field.

Built on top of #6201.
2022-07-05 16:20:56 -07:00
Jacob Hoffman-Andrews c65329202e
ra: add GenerateOCSP (#6192)
Add a new `GenerateOCSP` gRPC method to the RA, which
passes the request through to the CA and returns the resulting
OCSP response bytes. This method does not store the new
response anywhere, it is up to the client (in this case intended to
be the new ocsp-responder's live-signing code path) to store it
in any/all appropriate locations.

Fixes #6189
2022-06-27 16:04:42 -07:00
Aaron Gable f3baa11440
SA: Add GetRevokedCerts method (#6170)
Add a new SA gRPC method named `GetRevokedCerts`. This method takes as
input an `IssuerNameID` and starting and ending timestamps, and queries
the database for all certificates issued by that issuer whose `NotAfter`
timestamp is in the indicated period. It returns a stream of `CRLEntry`,
one message for each row in the database query result.

This query has been shown to be reasonably fast, taking less than 20
seconds to scan 24 hours of prod issuance.

Fixes #6160
2022-06-27 13:33:40 -07:00
Aaron Gable b86e9d10da
Unify how we do streaming database selects (#6176)
Create a new type `db.MappedSelector` which exposes a new
`Query` method. This method behaves similar to gorp's
`SelectFoo` methods, in that it uses the desired result type to
look up the correct table to query and uses reflection to map
the table columns to the struct fields. It behaves similarly to
the stdlib's `sql.Query` in that it returns a `Rows` object which
can be iterated over to get one row of results at a time. And it
improves both of those by using generics, rather than `interface{}`,
to provide a nicely-typed calling interface.

Use this new type to simplify the existing streaming query in
`SerialsForIncident`. Similarly use the new type to simplify
rocsp-tool's and ocsp-updater's streams of `CertStatusMetadata`.
This new type will also be used by the crl-updater's upcoming
`GetRevokedCerts` streaming query.

Fixes #6173
2022-06-24 14:31:46 -07:00
Jacob Hoffman-Andrews 41d121704a
Remove comments about finished deprecations (#6152) 2022-06-14 14:23:30 -07:00
Aaron Gable f7ab64f05b
Remove last references to CFSSL (#6155)
Just a docs and config cleanup.
2022-06-14 14:22:34 -07:00
Aaron Gable 9b4ca235dd
Update boulder-tools dependencies (#6129)
Update:
- golangci-lint from v1.42.1 to v1.46.2
- protoc from v3.15.6 to v3.20.1
- protoc-gen-go from v1.26.0 to v1.28.0
- protoc-gen-go-grpc from v1.1.0 to v1.2.0
- fpm from v1.14.0 to v1.14.2

Also remove a reference to go1.17.9 from one last place.

This does result in updating all of our generated .pb.go files, but only
to update the version number embedded in each file's header.

Fixes #6123
2022-05-20 14:24:01 -07:00
Aaron Gable 5e11772e49
Simplify SA gRPC stream test scaffolding (#6068)
When testing the SA from within the SA package itself, we can directly
call its methods without having to go through the gRPC client interface.
Rather than needing to mock out gRPC client and server streams that
talk to each other over a channel, we can simply mock the server stream
and read from it directly.

The inMemSA adapter work will still be necessary when (for example)
testing an RA which uses a real in-memory SA to serve as its test
backend, rather than mocking out the SA. In that case, we need to wrap
the `storageAuthorityImpl` in something which causes it to match the
`sapb.StorageAuthorityClient` interface expected by the RA. That's what
the `//test/inmem/` package is for, and we'll move this wrapper code there
when we need it.

By testing these methods directly, rather than through an inmem wrapper,
we remove a potential cyclic import that was preventing us from moving
the inmem stream adapter into the `//test/inmem` package itself.
2022-05-12 10:00:00 -07:00
Aaron Gable 8cb01a0c34
Enable additional linters (#6106)
These new linters are almost all part of golangci-lint's collection
of default linters, that would all be running if we weren't setting
`disable-all: true`. By adding them, we now have parity with the
default configuration, as well as the additional linters we like.

Adds the following linters:
* unconvert
* deadcode
* structcheck
* typecheck
* varcheck
* wastedassign
2022-05-11 13:58:58 -07:00
Aaron Gable f29f63a317
Don't write "null" to DB for missing contacts (#6090)
Instead write `[]`, a better representation of an empty contact set,
and avoid having literal JSON `null`s in our database.

As part of doing so, add some extra code to //sa/model.go that
bypasses the need for //sa/type-converter.go to do any magic
JSON-to-string-slice conversions for us.

Fixes #6074
2022-05-10 09:25:41 -07:00
Jacob Hoffman-Andrews fe6fab8821
Remove fqdnsets_old workaround (#6054)
Fixes #5670
2022-04-21 16:39:35 -07:00
Samantha e0de2f6610
SA: Add support for querying which serials are impacted by a given incident (#6034)
- Add protobuf types `SerialsForIncidentRequest` and `IncidentSerial`
- Rename `incidentCertModel` to `incidentSerialModel`
- Add new SA method `SerialsForIncident`
- Add streaming GRPC adapter to allow for unit testing `SerialsForIncident`
  
Fixes #5947
2022-04-14 12:47:36 -07:00
Jacob Hoffman-Andrews 42c6eacd0f
Remove old challModel code (#6048)
This is no longer needed since the move to authz2.
2022-04-13 16:26:17 -07:00
Samantha 82c20145c9
SA: Add support for querying which incidents impact a given serial (#6026)
First commit adding support for tooling to aid in the tracking and remediation
of incidents.

- Add new SA method `IncidentsForSerial`
- Add database models for `incident`s and `incidentCert`s
- Add protobuf type for `incident`
- Add database migrations for `incidents`, `incident_foo`, and `incident_bar`
- Give db user `sa` permissions to  `incidents`, `incident_foo`, and
  `incident_bar`
  
 Part Of #5947
2022-04-07 14:44:59 -07:00
Andrew Gabbitas 87ef1b4934
Use OCSP NextUpdate to calculate Redis TTL (#6031) 2022-04-04 15:18:11 -06:00
Andrew Gabbitas e2b49dbe0a
Support writing OCSP to Redis on revocation (#6012)
If a Redis client is configured for the SA service, OCSP responses created
during a revocation event will be written to Redis on a best effort basis.

Use the OCSP response NextUpdate time as the expiration time for the
redis entry. Change the new issuance OCSP storage to do the same.

Fixes #5888
2022-04-01 13:59:56 -06:00
Andrew Gabbitas 79048cffba
Support writing initial OCSP response to redis (#5958)
Adds a rocsp redis client to the sa if cluster information is provided in the
sa config. If a redis cluster is configured, all new certificate OCSP
responses added with sa.AddPrecertificate will attempt to be written to
the redis cluster, but will not block or fail on errors.

Fixes: #5871
2022-03-21 20:33:12 -06:00
Aaron Gable 07d56e3772
Add new, simpler revocation methods to RA (#5969)
Add two new gRPC methods to the SA:
- `RevokeCertByKey` will be used when the API request was signed by the
  certificate's keypair, rather than a Subscriber keypair. If the
  request is for reason `keyCompromise`, it will ensure that the key is
  added to the blocked keys table, and will attempt to "re-revoke" a
  certificate that was already revoked for some other reason.
- `RevokeCertByApplicant` supports both the path where the original
  subscriber or another account which has proven control over all of the
  identifier in the certificate requests revocation via the API. It does
  not allow the requested reason to be `keyCompromise`, as these
  requests do not represent a demonstration of key compromise.

In addition, add a new feature flag `MozRevocationReasons` which
controls the behavior of these new methods. If the flag is not set, they
behave like they have historically (see above). If the flag is set to true,
then the new methods enforce the upcoming Mozilla policies around
revocation reasons, namely:
- Only the original Subscriber can choose the revocation reason; other
  clients will get a set reason code based on the method of requesting
  revocation. When the original Subscriber requests reason
  `keyCompromise`, this request will be honored, but the key will not be
  blocked and other certificates with that key will not also be revoked.
- Revocations signed with the certificate key will always get reason
  `keyCompromise`, because we do not know who is sending the request and
  therefore must assume that the use of the key in this way represents
  compromise. Because these requests will always be fore reason
  `keyCompromise`, they will always be added to the blocked keys table
  and they will always attempt "re-revocation".
- Revocations authorized via control of all names in the cert will
  always get reason `cessationOfOperation`, which is to be used when the
  original Subscriber does not control all names in the certificate
  anymore.

Finally, update the existing `AdministrativelyRevokeCertificate` method
to use the new helper functions shared by the two new methods.

Part of #5936
2022-03-14 08:58:17 -07:00
Aaron Gable 745e69e7f9
Add UpdateRevokedCertificate method to SA (#5962)
Add a new gRPC method `UpdateRevokedCertificate` to the SA. This
method takes the same argument as the existing `RevokeCertificate` RPC,
but only operates on certificates that have already been revoked with a
reason other than keyCompromise (c.f. `RevokeCertificate`, which only
operates on certificates that have not been revoked).

One thing to be careful of here is that storing an updated revocation reason
should not also change the revocation date. To support this, add a new field
to the existing `RevokeCertificateRequest` that allows us to differentiate the
time at which the new OCSP response was created, and the time at which
the revocation went into effect.

Part of #5936
2022-02-28 14:22:12 -08:00
Aaron Gable 9fe411185a
Don't use magic strings for authz statuses (#5911)
We have the `core.AcmeStatus` type precisely so that we don't have to
rely on correctly typing the word `"pending"` everywhere. Use those values
instead of raw strings when converting between string-like Authz statuses
and the database bitfield.
2022-02-11 16:00:19 -08:00
Aaron Gable 305ef9cce9
Improve error checking paradigm (#5920)
We have decided that we don't like the if err := call(); err != nil
syntax, because it creates confusing scopes, but we have not cleaned up
all existing instances of that syntax. However, we have now found a
case where that syntax enables a bug: It caused readers to believe that
a later err = call() statement was assigning to an already-declared err
in the local scope, when in fact it was assigning to an
already-declared err in the parent scope of a closure. This caused our
ineffassign and staticcheck linters to be unable to analyze the
lifetime of the err variable, and so they did not complain when we
never checked the actual value of that error.

This change standardizes on the two-line error checking syntax
everywhere, so that we can more easily ensure that our linters are
correctly analyzing all error assignments.
2022-02-01 14:42:43 -07:00
Samantha f69b57e0e1
Make DB client initialization uniform and stop setting 'READ-UNCOMMITTED' (#5741)
Boulder components initialize their gorp and gorp-less (non-wrapped) database
clients via two new SA helpers. These helpers handle client construction,
database metric initialization, and (for gorp only) debug logging setup.

Removes transaction isolation parameter `'READ-UNCOMMITTED'` from all database
connections.

Fixes #5715 
Fixes #5889
2022-01-31 13:34:23 -08:00
Aaron Gable a8f9fe5bb4
Check error after inserting precert ocsp status (#5918)
We insert the precertificate and its ocsp status inside a transaction,
to make sure that they either both succeed or both fail. However, we
were failing to check the error return after inserting the ocsp response.
Add a check to ensure that we fail the whole transaction if the certStatus
insert fails, and add a test to cover this case.
2022-01-28 20:40:16 -08:00
Aaron Gable fffd05e2a5
Correctly handle revoked authzs for order status (#5912)
We have no automated processes which transition Authorizations into
the "revoked" status. Therefore the code which compute the status of
an Order based on the status of its associated Authorizations did not
handle Authorizations with status `core.StatusRevoked`. This code
started failing (by falling through to its default case) when Revoked
Authorizations were introduced to the database.

Unfortunately, the `statusForOrder` function is called during /new-order
handling, to determine whether an existing Order can be reused for
the new request. This means that clients attempting to place a new
order for which there was a candidate existing order were getting 500s,
rather than getting either a new or reused Order object.

To fix the error, introduce a new case which handles `core.StatusRevoked`.
Also collapse the various integer counters which were all just counting
"any status other than Valid or Pending" into a single counter.

This bug would have been avoided by Rust's requirement that case
switches cover all of their possible branches.
2022-01-26 16:50:49 -08:00
Aaron Gable ab79f96d7b
Fixup staticcheck and stylecheck, and violations thereof (#5897)
Add `stylecheck` to our list of lints, since it got separated out from
`staticcheck`. Fix the way we configure both to be clearer and not
rely on regexes.

Additionally fix a number of easy-to-change `staticcheck` and
`stylecheck` violations, allowing us to reduce our number of ignored
checks.

Part of #5681
2022-01-20 16:22:30 -08:00
Aaron Gable 18389c9024
Remove dead code (#5893)
Running an older version (v0.0.1-2020.1.4) of `staticcheck` in
whole-program mode (`staticcheck --unused.whole-program=true -- ./...`)
finds various instances of unused code which don't normally show up
as CI issues. I've used this to find and remove a large chunk of the
unused code, to pave the way for additional large deletions accompanying
the WFE1 removal.

Part of #5681
2022-01-19 12:23:06 -08:00
Aaron Gable 3b9f3dc000
Remove functionality of NewAuthorization flow (#5862)
Empty the bodies of the WFE's and RA's `NewAuthorization` methods. These
were used exclusively by the ACMEv1 flow. Also remove any helper functions
which were used exclusively by this code, and any tests which were testing
exclusively this code and which have equivalent tests for the ACMEv2 flow.

Greatly simply `SA.GetAuthorizations2`, as it no longer has to contend with
there being two different kinds of authorizations in the database. Add a few
TODOs to consider removing a few other SA gRPC methods which no longer
have any callers.

Part of #5681
2021-12-20 14:39:11 -08:00
Aaron Gable c7643992a0
Enable USE INDEX hints when querying authz2 table (#5823)
Add a new feature flag `GetAuthzUseIndex` which causes the SA
to add `USE INDEX (regID_identifer_status_expires_idx)` to its authz2
database queries. This should encourage the query planner to actually
use that index instead of falling back to large table-scans.

Fixes #5822
2021-12-01 14:48:09 -08:00
Jacob Hoffman-Andrews 573700711c
Add ID field to Certificate and CertificateStatus (#5809)
Also go back to using Gorp's Insert method to insert CertificateStatus.

In b557d870c7, we switched from Insert to an Exec
with explicitly listed fields, as a temporary measure for a table migration
(related to StoreIssuerInfo). In 3d9c31580a,
with the migration done and the feature flag turned on, we cleaned up the
feature flag but did not revert back to an Insert. This finishes that cleanup.

Adding the ID field (and telling Gorp it's the primary key) to Certificate
and CertificateStatus objects is useful for writing tests that rely on the
ID field. It also removes a little hack where `CertStatusMetadata` had an
ID field because CertificateStatus didn't.
2021-11-25 10:29:10 -08:00
Aaron Gable 8eb7272adf
SA: Use read-only connector for GetAuthorizations2 (#5815)
Add a feature flag which causes the SA to switch between using the
traditional read-write database connector (pointed at the primary db)
or the newer read-only database connector (usually pointed at a
replica) when executing the `GetAuthorizations2` query.
2021-11-24 16:57:42 -08:00
Jacob Hoffman-Andrews 44d9d50a92
Check column names in ScanCertStatusMetadataRow (#5776)
This ensures we queried the right set of columns, and didn't get them
out of order.
2021-11-05 10:51:15 -07:00
Andrew Gabbitas 98d9a12ccd
Use authorization attemptedAt date for CAA recheck (#5746)
When a valid authorization is stored in the database the authorization
column attemptedAt is set based on the challenge `Validated` value. Use
this value in `checkAuthorizationsCAA` to determine if an authorization
is sufficiently stale to need a recheck of the CAA DNS record. Error if the
time is nil. Keeps old codepath for safety check and increments a metric
if the old codepath is used.
2021-11-04 14:50:11 -06:00
Aaron Gable 6d3d80fdc6
ocsp-updater: use ID instead of Serial for updates (#5762)
Update the SA's CertStatusMetadata methods to include the "id"
column in the resulting object; also create a new struct representing
this object and delete the old unused methods. Plumb this id through
all of ocsp-updater, and use it in the SQL queries which update row
with new Expired statuses or with newly-signed OCSP responses.

This should allow the updates to be ever-so-slightly more efficient.

Fixes #5655
Fixes #5587
2021-11-01 15:24:03 -07:00
Samantha 6e6f452945
admin-revoker: tool should only need to query the `precertificates` table (#5737)
- Add new function `SelectPrecertificates` to `SA` which returns `[]CertWithID`
- Replace `admin-revoker` calls to `sa.SelectCertificate(s)` with sa.SelectPrecertificate(s)
- Add SQL permissions for the `revoker` user to the `precertificates` table

Fixes #5708
2021-10-22 18:31:30 -07:00
Samantha 99502b1ffb
oscp-updater: use rows.Scan() to get query results (#5656)
- Replace `gorp.DbMap` with calls that use `sql.DB` directly
- Use `rows.Scan()` and `rows.Next()` to get query results (which opens the door to streaming the results)
- Export function `CertStatusMetadataFields` from `SA`
- Add new function `ScanCertStatusRow` to `SA`
- Add new function `NewDbSettingsFromDBConfig` to `SA`

Fixes #5642
Part Of #5715
2021-10-18 10:33:09 -07:00
Aaron Gable bab688b98f
Remove sa-wrappers.go (#5663)
Remove the last of the gRPC wrapper files. In order to do so:

- Remove the `core.StorageGetter` interface. Replace it with a new
  interface (whose methods include the `...grpc.CallOption` arg)
  inside the `sa/proto/` package.
- Remove the `core.StorageAdder` interface. There's no real use-case
  for having a write-only interface.
- Remove the `core.StorageAuthority` interface, as it is now redundant
  with the autogenerated `sapb.StorageAuthorityClient` interface.
- Replace the `certificateStorage` interface (which appears in two
  different places) with a single unified interface also in `sa/proto/`.
- Update all test mocks to include the `_ ...grpc.CallOption` arg in
  their method signatures so they match the gRPC client interface.
- Delete many methods from mocks which are no longer necessary (mostly
  because they're mocking old authz1 methods that no longer exist).
- Move the two `test/inmem/` wrappers into their own sub-packages to
  avoid an import cycle.
- Simplify the `satest` package to satisfy one of its TODOs and to
  avoid an import cycle.
- Add many methods to the `test/inmem/sa/` wrapper, to accommodate all
  of the methods which are called in unittests.

Fixes #5600
2021-09-27 13:25:41 -07:00
Aaron Gable 6c85ae0f2c
expiration-mailer: improve search for renewals (#5673)
Overhaul how expiration-mailer checks to see if a `certIsRenewed`.
First, change the helper function to take the list of names (which
can be hashed into an fqdnSet) and the issuance date. This allows the
search for renewals to be a much simpler linear scan rather than an
ugly outer left join. Second, update the query to examine both the
`fqdnSets` and `fqdnSets_old` tables, to account for the fact that
this code cares about more time (~90d) than the `fqdnSets` table
currently holds.

Also export the SA's `HashNames` method so it can be used by the mailer,
and update the mailer's tests to use correct name hashes instead of
fake human-readable hashes.

Fixes #5672
2021-09-24 13:36:57 -07:00
Aaron Gable f21ba0d8a7
Check both current and old fqdnSets tables (#5668)
In `sa.checkFQDNSetExists`, query both the normal `fqdnSets` and the
`fqdnSets_old` tables. The `fqdnSets` table was recently truncated to
only have 7 days worth of data, but this helper function is used to
bypass other rate limits if there exists a prior certificate for the
exact same set of names, and that functionality cares about at least
90 days worth of data. Therefore we need to query both tables, at least
until `fqdnSets` contains 90 days worth of data again.

Also make a variety of other changes to support this change: creating
the `fqdnSets_old` table in our test environment, documenting various
places where it needs to be cleaned up, and removing some unused code.

Fixes #5671
2021-09-24 12:34:25 -07:00
Aaron Gable 52c865f621
Fix typo in certStatusMetadata methods (#5644)
Change #5635 added new methods to the SA to select just
certificateStatus metadata columns, without selecting the
ocspResponse bytes themselves. However, one of those new
methods accidentally still called an old helper method, and
so the change had no effect overall.

Change the helper method to be the correct metadata helper.

Fixes #5632
2021-09-07 18:20:57 -07:00
Aaron Gable 1a4b40d2ce
ocsp-updater: don't retrieve ocsp response bytes (#5633)
Create a new set of methods in the SA which are designed to work with
just certificate status metadata, not the current OCSP response itself.
Use these new methods from the ocsp-updater, so that it isn't taking the
database cpu time or the network bandwidth to handle those large byte
blobs that it doesn't even care about.

Also, remove the old `SelectCertificateStatuses` (plural) method, because
its only user was the ocsp-updater.

Fixes #5632
2021-09-07 11:03:08 -07:00
Aaron Gable 4ef9fb1b4f
Add new SA.NewOrderAndAuthzs gRPC method (#5602)
Add a new method to the SA's gRPC interface which takes both an Order
and a list of new Authorizations to insert into the database, and adds
both (as well as the various ancillary rows) inside a transaction.

To enable this, add a new abstraction layer inside the `db/` package
that facilitates inserting many rows at once, as we do for the `authz2`,
`orderToAuthz2`, and `requestedNames` tables in this operation. 

Finally, add a new codepath to the RA (and a feature flag to control it)
which uses this new SA method instead of separately calling the
`NewAuthorization` method multiple times. Enable this feature flag in
the config-next integration tests.

This should reduce the failure rate of the new-order flow by reducing
the number of database operations by coalescing multiple inserts into a
single multi-row insert. It should also reduce the incidence of new
authorizations being created in the database but then never exposed to
the subscriber because of a failure later in the new-order flow, both by
reducing failures overall and by adding those authorizations in a
transaction which will be rolled back if there is a later failure.

Fixes #5577
2021-09-03 13:48:04 -07:00
Samantha d1d04c950e
GRCP: Replace `CountByNames_MapElement` with a real proto map (#5621)
Fixes  #5614
2021-09-03 13:12:52 -07:00
Andrew Gabbitas 4967f0f932
GRPC Unwrap: Make sa.SetOrderError passthrough (#5606)
* Make `sa.SetOrderError` passthrough.
* Create new proto message `sapb.SetOrderErrorRequest`
  that includes only the order id and error to avoid passing around
  unnecessary fields of an order.

Part of: #5533
2021-09-01 13:00:40 -06:00
Andrew Gabbitas 818e01d3db
GRPC Unwrap: Make sa.NewOrder passthrough (#5615)
* Make `sa.NewOrder` passthrough. 
* Create a new proto message `sapb.NewOrderRequest`
   that includes only the information needed to store a new order.

Part of: #5533
2021-08-31 21:35:38 -06:00
Andrew Gabbitas 63f26a7a68
GRPC Unwrap: Make sa.FinalizeOrder passthrough (#5619)
* Make sa.FinalizeOrder grpc wrapper a passthrough.
* Create and use new proto message `FinalizeOrderRequest`.

Part of: #5533
2021-08-31 17:06:28 -06:00
Andrew Gabbitas e8e907b443
GRPC Unwrap: Make sa.SetOrderProcessing passthrough (#5604)
* Make sa.SetOrderProcessing GRPC wrapper passthrough. Also, change the
  server method to accept an `*sapb.OrderRequest{}` (essentially just an
  order ID) as the parameter instead of a whole order.

Part of: #5533
2021-08-31 16:14:25 -06:00
Aaron Gable 1bf857ac09
Unwrap SA FQDNSet and PreviousCertificate existence methods (#5618)
Fixes #5532
2021-08-31 09:22:16 -06:00
Aaron Gable 38dd2392d4
Unwrap sa.GetCertificateStatus (#5610)
Turn the `GetCertificateStatus` wrappers into pass-throughs.

Part of #5532
2021-08-30 16:35:34 -07:00
Samantha 5e8744c425
GRPC: Unwrap SA Count methods (#5616)
- Make `CountRegistrationsByIP` a pass-through
- Make `CountRegistrationsByIPRange` a pass-through
- Make `CountOrders` a pass-through
- Make `CountFQDNSets` a pass-through
- Make `CountPendingAuthorizations2` a pass-through
- Make `CountInvalidAuthorizations2` a pass-through

Fixes #5535
2021-08-30 15:54:42 -07:00
Samantha 9d840f9b2f
GRPC: Unwrap sa.CountCertificatesByNames (#5612)
Part of #5535
2021-08-30 15:02:44 -07:00
Samantha 279c759ca2
GRPC: Unwrap SA Authorization methods (#5589)
- Make `GetAuthorization2` a pass-through
- Make `GetAuthorizations2` a pass-through
- Make `GetPendingAuthorization2` a pass-through
- Make `GetValidOrderAuthorizations2` a pass-through
- Make `GetValidAuthorizations2` a pass-through
- Make `NewAuthorizations2` a pass-through
- Make `FinalizeAuthorization2` a pass-through
- Make `DeactivateAuthorization2` a pass-through

Fixes #5534
2021-08-26 15:31:23 -07:00
Andrew Gabbitas 89a803edaa
GRPC Unwrap: Make sa.GetOrderForNames passthrough (#5603)
Part of: #5533
2021-08-26 13:43:00 -06:00
Aaron Gable 2fe12cdf20
Unwrap SA Add/Revoke Certificate methods (#5598)
Make the gRPC wrappers for the SA's `AddCertificate`,
`AddPrecertificate`, `AddSerial`, and `RevokeCertificate`
methods simple pass-throughs.

Fixup a couple tests that were passing only because their
requests to in-memory SA objects were not passing through
the wrapper's consistency checks.

Part of #5532
2021-08-25 15:54:25 -07:00
Andrew Gabbitas 443862bd13
GRPC Unwrapping: make sa.GetOrder passthrough (#5596)
Part of: #5533
2021-08-25 14:21:58 -06:00
Aaron Gable f454892dd1
Unwrap SA Get[Pre]Certificate methods (#5588)
Make the gRPC wrappers for sa.GetCertificate and
sa.GetPrecertificate bare passthroughs. The latter of
these already took and returned appropriate protobufs,
so this change mostly just makes the former look like the
latter.

Part of #5532
2021-08-19 15:43:48 -07:00
J.C. Jones f71a17add4
Batch multiple authz into single SQL statements (#5576)
Batch all new authorizations to be inserted into the database into a
single SQL `INSERT` statement, rather than inserting each row one
at a time. Also add a unit test which inserts 100 authzs to test this
new batching behavior.

Since each statement has significant cost, when there are a lot
of authorizations to insert at a time, the round-trips here can
eat up a lot of time both on the SA and on the database, as it
works to commit each statement as its own transaction. gorp does
not have any means to automatically make multi-value inserts, so
we do it in a bespoke fashion here, somewhat akin to what we
already do in AddBlockedKey and addIssuedNames but with more
loops.

Fixes #5578
2021-08-16 08:50:43 -07:00
Aaron Gable b7ce627572
Remove SA Registration gRPC wrappers (#5551)
Remove all error checking and type transformation from the gRPC wrappers
for the following methods on the SA:
- GetRegistration
- GetRegistrationByKey
- NewRegistration
- UpdateRegistration
- DeactivateRegistration

Update callers of these methods to construct the appropriate protobuf
request messages directly, and to consume the protobuf response messages
directly. In many cases, this requires changing the way that clients
handle the `Jwk` field (from expecting a `JSONWebKey` to expecting a
slice of bytes) and the `Contacts` field (from expecting a possibly-nil
pointer to relying on the value of the `ContactsPresent` boolean field).

Implement two new methods in `sa/model.go` to convert directly between
database models and protobuf messages, rather than round-tripping
through `core` objects in between. Delete the older methods that
converted between database models and `core` objects, as they are no
longer necessary.

Update test mocks to have the correct signatures, and update tests to
not rely on `JSONWebKey` and instead use byte slices.

Fixes #5531
2021-08-04 13:33:41 -07:00
J.C. Jones 7b31bdb30a
Add read-only dbConns to SQLStorageAuthority and OCSPUpdater (#5555)
This changeset adds a second DB connect string for the SA for use in 
read-only queries that are not themselves dependencies for read-write 
queries. In other words, this is attempting to only catch things like 
rate-limit `SELECT`s and other coarse-counting, so we can potentially 
move those read queries off the read-write primary database.

It also adds a second DB connect string to the OCSP Updater. This is a 
little trickier, as the subsequent `UPDATE`s _are_ dependent on the 
output of the `SELECT`, but in this case it's operating on data batches,
and a few seconds' replication latency are several orders of magnitude 
below the threshold for update frequency, so any certificates that 
aren't caught on run `n` can be caught on run `n+1`.

Since we export DB metrics to Prometheus, this also refactors 
`InitDBMetrics` to take a DB Address (host:port tuple) and User out of 
the DB connection DSN and include those as labels in the metrics.

Fixes #5550
Fixes #4985
2021-08-02 11:21:34 -07:00
Andrew Gabbitas ad34089cda
Check for duplicate certs before adding to db (#5497)
* Check for duplicate certs before adding to db

Error at SA if the certificate or precertificate already exist in the
database

Fixes: #5468
2021-07-08 12:51:57 -06:00
Samantha fa30f17fe7
SA: Add resiliency for duplicate certificates encountered by SelectCertificate (#5500)
- Add `LIMIT 1` to the `SelectCertificate` query
- Modify unit test `TestCerficatesTableContainsDuplicateSerials`

Part of #5467
2021-07-07 13:33:32 -07:00
Samantha fd7427a243
SA: Add unit tests for SelectCertificate (#5503)
Add unit tests for SelectCertificate

   - Test happy path
   - Test duplicate certificate for serial error

Part of #5467
2021-06-23 16:45:08 -07:00
Samantha 8ea2657341
SA: Promote partition migrations from db-next (#5502)
Part of #5467
2021-06-23 11:52:35 -07:00
Aaron Gable 64c9ec350d
Unify protobuf generation (#5458)
Create script which finds every .proto file in the repo and correctly
invokes `protoc` for each. Create a single file with a `//go:generate`
directive to invoke the new script. Delete all of the other generate.go
files, so that our proto generation is unified in one place.

Fixes #5453
2021-06-07 08:49:15 -07:00
Aaron Gable 8be32d3312
Use google.protobuf.Empty instead of core.Empty (#5454)
Replace `core.Empty` with `google.protobuf.Empty` in all of our gRPC
methods which consume or return an empty protobuf. The golang core
proto libraries provide an empty message type, so there is no need
for us to reinvent the wheel.

This change is backwards-compatible and does not require a special
deploy. The protobuf message descriptions of `core.Empty` and
`google.protobuf.Empty` are identical, so their wire-formats are
indistinguishable and therefore interoperable / cross-compatible.

Fixes #5443
2021-06-03 14:17:41 -07:00
Andrew Gabbitas 59bab8bac4
Make core.Registration.CreatedAt a *time.Time (#5422)
* Make core.Registration.CreatedAt a *time.time

Fixes: #5421
2021-05-21 13:44:56 -06:00
Jacob Hoffman-Andrews 7194624191
Update grpc and protobuf to latest. (#5369)
protoc now generates grpc code in a separate file from protobuf code.
Also, grpc servers are now required to embed an "unimplemented"
interface from the generated .pb.go file, which provides forward
compatibility.

Update the generate.go files since the invocation for protoc has changed
with the split into .pb.org and _grpc.pb.go.

Fixes #5368
2021-04-01 17:18:15 -07:00
Aaron Gable 5a006f8b51
SQL: Drop foreign keys and partition tables (#5322)
Add paritions to the authz2, certificates, fqdnSets, orderFqdnSets,
orderToAuthz2, requestedNames, orders, and precertificates tables.
In order to allow such partitions, also drop various unique indices
and foreign keys on the same tables.

Dropping these indices is safe because we have other mechanisms to
enforce uniqueness. For example, the fqdnSets table does not need
to enforce uniqueness of serials because that constraint is enforced
by the serials table itself.

Fixes #5298, #5267, #5268
2021-03-16 13:16:08 -07:00
Samantha fc53482cac
Run db-next migrations with config-next configuration (#5320)
Docker container should load the appropriate schema (`sa/_db` or
`sa/_db-next`) for the given configuration.

- Add `docker-compose.next.yml` docker-compose overrides
- Detect when to apply `sa/_db-next/migrations`
- Detect mismatch between `goose dbversion` and the latest migration
- Symlink `promoted` schema back to `sa/_db-next/migrations`
- Add tooling to consistently promote/demote schema migrations

Fixes #5300
2021-03-11 14:45:32 -08:00
Andrew Gabbitas f5362fba24
Add Validated time field to challenges (#5288)
Move the validated timestamp to the RA where the challenge is passed to
the SA for database storage. If a challenge becomes valid or invalid, take
the validated timestamp and store it in the attemptedAt field of the
authz2 table. Upon retrieval of the challenge from the database, add the
attemptedAt value to challenge.Validated which is passed back to the WFE
and presented to the user as part of the challenge as required in ACME
RFC8555.

Fix: #5198
2021-03-10 14:39:59 -08:00
Aaron Gable a7f5917fb1
Fix bad merge from #5305 (#5309)
Remove two database migration files which were added immediately
prior to 5305, and which should have been removed by it, but were
left in place due to weird git merge semantics.
2021-02-25 13:03:36 -07:00