Commit Graph

28 Commits

Author SHA1 Message Date
James Renken 7214b285e4
identifier: Remove helper funcs from PB identifiers migration (#8236)
Remove `ToDNSSlice`, `FromProtoWithDefault`, and
`FromProtoSliceWithDefault` now that all their callers are gone. All
protobufs but one have migrated from DnsNames to Identifiers.

Remove TODOs for the exception, `ValidationRecord`, where an identifier
type isn't appropriate and it really only needs a string.

Rename `corepb.ValidationRecord.DnsName` to `Hostname` for clarity, to
match the corresponding PB's field name.

Improve various comments and docs re: IP address identifiers.

Depends on #8221 (which removes the last callers)
Fixes #8023
2025-06-13 12:55:32 -07:00
James Renken ac68828f43
Replace most uses of net.IP with netip.Addr (#8205)
Retain `net.IP` only where we directly work with `x509.Certificate` and
friends.

Fixes #5925
Depends on #8196
2025-05-27 15:05:35 -07:00
James Renken 3e6a8e2d25
va: Support IP address identifiers (#8020)
Add an `identifier` field to the `va.PerformValidationRequest` proto, which will soon replace its `dnsName` field.

Accept and prefer the `identifier` field in every VA function that uses this struct. Don't (yet) assume it will be present.

Throughout the VA, accept and handle the IP address identifier type. Handling is similar to DNS names, except that `getAddrs` is not called, and consider that:
- IPs are represented in a different field in the `x509.Certificate` struct.
- IPs must be presented as reverse DNS (`.arpa`) names in SNI for [TLS-ALPN-01 challenge requests](https://datatracker.ietf.org/doc/html/rfc8738#name-tls-with-application-layer-).
- IPv6 addresses are enclosed in square brackets when composing or parsing URLs.

For HTTP-01 challenges, accept redirects to bare IP addresses, which were previously rejected.

Fixes #2706
Part of #7311
2025-03-06 11:39:22 -08:00
Aaron Gable 46859a22d9
Use consistent naming for dnsName gRPC fields (#7654)
Find all gRPC fields which represent DNS Names -- sometimes called
"identifier", "hostname", "domain", "identifierValue", or other things
-- and unify their naming. This naming makes it very clear that these
values are strings which may be included in the SAN extension of a
certificate with type dnsName.

As we move towards issuing IP Address certificates, all of these fields
will need to be replaced by fields which carry both an identifier type
and value, not just a single name. This unified naming makes it very
clear which messages and methods need to be updated to support
non-dnsName identifiers.

Part of https://github.com/letsencrypt/boulder/issues/7647
2024-08-12 14:32:55 -07:00
Aaron Gable a21c417bc0
Remove RSA KEX tracking from validation (#7629)
We used this data to inform our decision making, and have now fully
turned off support for RSA KEX during validation. This log event field
will now never be set, so it can be removed.

Part of https://github.com/letsencrypt/boulder/issues/7321
Fixes https://github.com/letsencrypt/boulder/issues/7628
2024-07-26 12:36:29 -04:00
Aaron Gable 09693f03dc
Deprecate Challenge.ProvidedKeyAuthorization (#7515)
The core.Challenge.ProvidedKeyAuthorization field is problematic, both
because it is poorly named (which is admittedly easily fixable) and
because it is a field which we never expose to the client yet it is held
on a core type. Deprecate this field, and replace it with a new
vapb.PerformValidationRequest.ExpectedKeyAuthorization field.

Within the VA, this also simplifies the primary logic methods to just
take the expected key authorization, rather than taking a whole (largely
unnecessary) challenge object. This has large but wholly mechanical
knock-on effects on the unit tests.

While we're here, improve the documentation on core.Challenge itself,
and remove Challenge.URI, which was deprecated long ago and is wholly
unused.

Part of https://github.com/letsencrypt/boulder/issues/7514
2024-06-04 14:48:36 -07:00
Aaron Gable b483ec2280
VA: Add metrics to measure key exchange cipher suites (#7322)
Add a new field to the structured JSON object logged by the VA
indicating whether the HTTP-01 or TLS-ALPN-01 requests ended up
negotiating a TLS cipher suite which uses RSA key exchange. This is
useful for measuring how many servers we reach out to are RSA-only, so
we can determine the deprecation timeline for RSA key exchange (which
has been removed from go1.22).

The go TLS library always prefers ECDHE key exchange over RSA, so we
should only be negotiating RSA key exchange if the server we're reaching
out to doesn't support ECDHE at all.

Part of https://github.com/letsencrypt/boulder/issues/7321
2024-02-13 17:44:23 -08:00
Jacob Hoffman-Andrews 3865b46638
va: return error instead of ProblemDetails (#7313)
This allows us to defer creating the user-friendly ProblemDetails to the
highest level (va.PerformValidation), which in turn makes it possible to
log the original error alongside the user-friendly error. It also
reduces the likelihood of "boxed nil" bugs.

Many of the unittests check for a specific ProblemDetails.Type and
specific Details contents. These test against the output of
`detailedError`, which transforms `error` into `ProblemDetails`. So the
updates to the tests include insertion of `detailedError(err)` in many
places.

Several places that were returning a specific ProblemDetails.Type
instead return the corresponding `berrors` type. This follows a pattern
that `berrors` was designed to enable: use the `berrors` types
internally and transform into `ProblemDetails` at the edge where we are
rendering something to present to the user: WFE, and now VA.
2024-02-12 11:34:49 -08:00
Phil Porada 0e9f5d3545
va: Audit log which DNS resolver performs a lookup (#7271)
Adds the chosen DNS resolver to the VAs `ValidationRecord` object so
that for each challenge type during a validation, boulder can audit log
the resolver(s) chosen to fulfill the request..

Fixes https://github.com/letsencrypt/boulder/issues/7140
2024-02-05 14:26:39 -05:00
Aaron Gable d57edfa0f1
Run more go vet checks (#7255)
Enable the atomicalign, deepequalerrors, findcall, nilness,
reflectvaluecompare, sortslice, timeformat, and unusedwrite go vet
analyzers, which golangci-lint does not enable by default. Additionally,
enable new go vet analyzers by default as they become available.

The fieldalignment and shadow analyzers remain disabled because they
report so many errors that they should be fixed in a separate PR.

Note that the nilness analyzer appears to have found one very real bug
in tlsalpn.go.
2024-01-17 12:27:55 -05:00
Aaron Gable 620699216f
Remove the TLS-ALPN-01 tlsDial helper (#6954)
This minor cleanup was found in the process of fixing tests in
https://github.com/letsencrypt/boulder/pull/6952, and resolves a TODO
from 2018.
2023-06-26 10:56:52 -07:00
Samantha a9ba5e42a0
VA: Add IP address to detailed errors (#6039)
Prepend the IP address of the remote host where HTTP-01 or TLS-ALPN-01
validation was attempted in the detailed error response body.

Fixes #6016
2022-04-13 12:55:35 -07:00
Aaron Gable ed912c3aa5
Remove duplication from TLS-ALPN-01 error messages (#6028)
Slightly refactor `validateTLSALPN01` to use a common function
to format the error messages it returns. This reduces code duplication
and makes the important validation logic easier to follow.

Fixes #5922
2022-04-04 09:17:16 -07:00
Aaron Gable cfab636c5a
TLS-ALPN-01: Check that challenge cert is self-signed (#5928)
RFC 8737 says "The client prepares for validation by constructing a self-signed
certificate...". Add a check for whether the challenge certificate is
self-signed by ensuring its issuer and subject are equal, and checking its
signature with its own public key.

Also slightly refactor the helper methods to return only a single cert, since we
only care about the first one returned. And add a test.
2022-02-02 16:45:13 -08:00
J.C. Jones f511442e84
Don't allow multiple certificate extensions from TLS-ALPN-01 (#5919)
Detect when a non-compliant ACME client presents a non-compliant x.509
certificate that contains multiple copies of the SubjectAlternativeName or ACME
Identifier extensions; this should be forbidden.
2022-02-01 13:37:51 -08:00
Aaron Gable 25f5e40e77
Require that TLS-ALPN-01 cert have only dnsNames (#5916)
RFC 8737 states that the certificate presented during the "acme-tls/1"
handshake has "a subjectAltName extension containing the dNSName
being validated and no other entries". We were checking that it contained
no other dNSNames, but not requiring that it not have any other kinds of
Subject Alternative Names.

Factor all of our SAN checks into a helper function. Have that function
construct the expected bytes of the SAN extension from the one DNS
name we expect to see, and assert that the actual bytes match the
expectation. Add non-DNS-name identifiers to our error output when we
encounter a cert whose SANs don't match. And add tests which check
that we fail the validation when the cert has multiple SANs.
2022-01-28 15:38:57 -08:00
Aaron Gable 4835709232
Remove support for obsolete id-pe-acmeIdentifier OID (#5906)
Current metrics show that subscribers present certificates using the
obsolete OID to identify their id-pe-acmeIdentifier extension about
an order of magnitude less often than they present the correct OID.
Remove support for the never-standardized OID.
2022-01-25 10:10:03 -08:00
Aaron Gable 8c28e49ab6
Enforce TLS1.2 when validating TLS-ALPN-01 (#5905)
RFC 8737, Section 4, states "ACME servers that implement "acme-tls/1"
MUST only negotiate TLS 1.2 [RFC5246] or higher when connecting to
clients for validation." Enforce that our outgoing connections to validate
TLS-ALPN-01 challenges do not negotiate TLS1.1.
2022-01-25 09:57:34 -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
Andrew Gabbitas 3d9d5e2306
Cleanup go1.15.7 (#5374)
Remove code that is no longer needed after migrating to go1.16.x.
Remove testing with go1.15.7 in the test matrix.

Fixes #5321
2021-04-01 10:50:18 -07:00
Andrew Gabbitas ceffe18dfc
Add testing for golang 1.16 (#5313)
- Add 1.16.1 to the GitHub CI test matrix
- Fix tlsalpn tests for go 1.16.1 but maintain compatibility with 1.15.x
- Fix integration tests.

Fix: #5301
Fix: #5316
2021-03-11 11:47:41 -08:00
Jacob Hoffman-Andrews 4a2029b293
Use explicit fmt.Sprintf for ProblemDetails (#4787)
In #3708, we added formatters for the the convenience methods in the
`probs` package.

However, in #4783, @alexzorin pointed out that we were incorrectly
passing an error message through fmt.Sprintf as the format parameter
rather than as a value parameter.

I proposed a fix in #4784, but during code review we concluded that the
underlying problem was the pattern of using format-style functions that
don't have some variant of printf in the name. That makes this wrong:
`probs.DNS(err.Error())`, and this right: `probs.DNS("%s", err)`. Since
that's an easy mistake to make and a hard one to spot during code review,
we're going to stop using this particular pattern and call `fmt.Sprintf`
directly.

This PR reverts #3708 and adds some `fmt.Sprintf` where needed.
2020-04-21 14:36:11 -07:00
Roland Bracewell Shoemaker 5b2f11e07e Switch away from old style statsd metrics wrappers (#4606)
In a handful of places I've nuked old stats which are not used in any alerts or dashboards as they either duplicate other stats or don't provide much insight/have never actually been used. If we feel like we need them again in the future it's trivial to add them back.

There aren't many dashboards that rely on old statsd style metrics, but a few will need to be updated when this change is deployed. There are also a few cases where prometheus labels have been changed from camel to snake case, dashboards that use these will also need to be updated. As far as I can tell no alerts are impacted by this change.

Fixes #4591.
2019-12-18 11:08:25 -05:00
Daniel McCarney 4a6e34fc4e
va: clean up DNS error handling for HTTP-01 challenges. (#4409)
This PR changes the VA to return `dns` problem type for errors when performing
HTTP-01 challenges for domains that have no IP addresses, or errors looking up
the IP addresses.

The `va.getAddrs` function is internal to the VA and can return
`berrors.BoulderError`s with a DNS type when there is an error, allowing the
calling code to convert this to a problem when required
using an updated `detailedError` function. This avoids some clunky conversion
the HTTP-01 code was doing that misrepresented DNS level errors as connection
problems with a DNS detail message.

In order to add an integration test for challenge validation that results in
`getAddrs` DNS level errors the Boulder tools image had to be bumped to a tag
that includes the latest `pebble-challtestsrv` that
supports mocking SERVFAILs. It isn't possible to mock this case with internal IP
addresses because our VA test configuration does not filter internal addresses
to support the testing context.

Additionally this branch removes the `UnknownHostProblem` from the `probs`
package:

1. It isn't used anywhere after 532c210
2. It's not a real RFC 8555 problem type. We should/do use the
   DNS type for this.

Resolves https://github.com/letsencrypt/boulder/issues/4407
2019-08-28 15:47:35 -04:00
alexzorin df2909a7ca va: Send extValue in TLSALPN unauthorized response (#4330)
Brings it to be more in line with the responses from the other two challenges and
will hopefully make the challenge a lot easier to debug (like in the recent community 
thread).

```json
"error": {
  "type": "urn:ietf:params:acme:error:unauthorized",
  "detail": "Incorrect validation certificate for tls-alpn-01 challenge. Expected acmeValidationV1 extension value 836bf5358f8a32826c61faeff2e0225b00756f935b00ed3002cabb9d536b9f53 for this challenge but got 8539b12e31c306b81a0aedab4128722c6ad71f71f46316a3c71612f47df0e532",
  "status": 403
},
```
2019-07-11 09:08:14 -07:00
Daniel McCarney ea9871de1e core: split identifier types into separate package. (#4225)
This will allow implementing sub-problems without creating a cyclic
dependency between `core` and `problems`.

The `identifier` package is somewhat small/single-purpose and in the
future we may want to move more "ACME" bits beyond the `identifier`
types into a dedicated package outside of `core`.
2019-05-23 13:24:41 -07:00
Daniel McCarney e050820fcc
va: add specific error for HTTP-01 to HTTP/2 server. (#4172)
In practice it seems the only way to add a specific error for when an initial HTTP-01 challenge request is made to an HTTP/2 server mis-configured on `:80` is with a regex on the error string.

The error returned from the stdlib `http.Client` for HTTP to an HTTP/2 server is just an `errors.ErrorString` instance without any context (once you peel it out of the wrapping `url.Error`):
>  Err:(*errors.errorString)(0xc420609bf0)}] errStr=[Get http://example.com/.well-known/acme-challenge/xxxxxxx: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x00\x00\x12\x04\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x80\x00\x04\x00\x01\x00\x00\x00\x05\x00\xff\xff\xff\x00\x00\x04\b\x00\x00\x00\x00\x00\u007f\xff\x00\x00\x00\x00\b\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"]

Even directly in the stdlib code at the place in `http/response.go` that generates the error it's using a `&badStringError{}` and just putting the byte string that `textproto` read into it.

To detect this case in `detailedError` I added a pre-compiled regex that will match the net/http malformed HTTP response error for raw bytes matching an arbitrarily sized HTTP/2 SETTINGS frame. Per RFC "A SETTINGS frame MUST be sent by both endpoints at the start of a connection" and so this seems like a fairly reliable indicator of an unexpected HTTP/2 response in an HTTP/1.1 context.

Thanks to @mnordhoff for the detailed notes (and RFC refs) in #3416 It made this a lot easier!

Resolves #3416.
2019-04-23 14:56:37 -04:00
Daniel McCarney cc0d15841f va: split up va.go by challenge type. (#4170)
When I introduced the new HTTP-01 code I did it in `va/http.go` intending to try and make the very large `va.go` file a little bit smaller. This is the continuation of that work.

* f96ad92 - moves remaining HTTP-01 specific code to `va/http.go`.
* 1efb9a1 - moves TLS-ALPN-01 code into `va/tlsalpn.go`.
* 95ea567 - moves DNS-01 code into `va/dns.go`.
* 6ff0395 - moves unit tests from `va/va_test.go` into `va/http_test.go`, `va/tlsalpn_test.go` and `va/dns_test.go`.

In the end `va/va.go` contains code related to metrics, top level RPCs (e.g. `PerformValidation`), and the multi-VA code. This makes the file lengths much more manageable overall.

Note: There is certainly room for cleaning up some of the older unit test cruft from `va/va_test.go`. For now I only moved it as-is into the challenge specific test files.
2019-04-19 11:34:58 -07:00