fix(ionosphere): disable TLS verify for GIRO to unbreak ionosonde fetch
lgdc.uml.edu's TLS handshake doesn't include the InCommon RSA Server CA 2 intermediate, and Erlang/OTP's chain decode trips on an ASN.1 table-constraint mismatch even when the intermediate is merged into the trust store. The data is public, read-only, unauthenticated ionosonde measurements, so verify_none is scoped to this one client rather than let the pipeline stay dark.
This commit is contained in:
parent
b92c1ea68b
commit
e8c252932a
2 changed files with 44 additions and 1 deletions
|
|
@ -56,7 +56,7 @@ defmodule Microwaveprop.Ionosphere.GiroClient do
|
|||
Microwaveprop.Instrument.span([:giro, :fetch], %{station: ursi_code}, fn ->
|
||||
url = build_url(ursi_code, from_dt, to_dt)
|
||||
|
||||
case Req.get(url, [receive_timeout: @default_timeout_ms] ++ req_options()) do
|
||||
case Req.get(url, [receive_timeout: @default_timeout_ms] ++ merged_req_options()) do
|
||||
{:ok, %{status: 200, body: body}} when is_binary(body) ->
|
||||
parse_tabular(body)
|
||||
|
||||
|
|
@ -192,4 +192,27 @@ defmodule Microwaveprop.Ionosphere.GiroClient do
|
|||
defp req_options do
|
||||
Application.get_env(:microwaveprop, :giro_req_options, [])
|
||||
end
|
||||
|
||||
# lgdc.uml.edu doesn't bundle the "InCommon RSA Server CA 2"
|
||||
# intermediate in its handshake. Adding the intermediate to our trust
|
||||
# store moves the error from unknown_ca to an Erlang/OTP asn1 table
|
||||
# constraint mismatch during chain decode — :ssl trips on an
|
||||
# extension shape it doesn't accept. Scope verify_none here is
|
||||
# acceptable: GIRO data is public, read-only, unauthenticated
|
||||
# ionosonde measurements, and the endpoint has no alternative. When
|
||||
# the test config overrides :giro_req_options with a Req.Test plug,
|
||||
# that override wins — :plug short-circuits before any TLS work, so
|
||||
# verify_none never runs in tests.
|
||||
defp merged_req_options do
|
||||
case req_options() do
|
||||
[] -> default_req_options()
|
||||
overrides -> overrides
|
||||
end
|
||||
end
|
||||
|
||||
@doc false
|
||||
@spec default_req_options() :: keyword()
|
||||
def default_req_options do
|
||||
[connect_options: [transport_opts: [verify: :verify_none]]]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -66,4 +66,24 @@ defmodule Microwaveprop.Ionosphere.GiroClientTest do
|
|||
assert row.valid_time == ~U[2026-04-15 18:07:30Z]
|
||||
end
|
||||
end
|
||||
|
||||
describe "default_req_options/0" do
|
||||
# lgdc.uml.edu's server doesn't bundle the "InCommon RSA Server CA 2"
|
||||
# intermediate, and Erlang/OTP's chain-build path trips over an
|
||||
# ASN.1 table-constraint mismatch even when the intermediate is
|
||||
# merged into cacerts. The data is public read-only ionosonde
|
||||
# measurements, so we accept verify_none for this specific endpoint
|
||||
# rather than keep the pipeline dark. Scope is limited to the GIRO
|
||||
# client — other HTTPS callers still verify normally.
|
||||
test "returns transport_opts with verify disabled for the GIRO endpoint" do
|
||||
opts = GiroClient.default_req_options()
|
||||
|
||||
transport_opts =
|
||||
opts
|
||||
|> Keyword.fetch!(:connect_options)
|
||||
|> Keyword.fetch!(:transport_opts)
|
||||
|
||||
assert Keyword.get(transport_opts, :verify) == :verify_none
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue