Skip to content

Commit 7a45e1a

Browse files
authored
Merge branch 'main' into feature/enforce-credo-code-quality
2 parents ea2dc9f + 962c841 commit 7a45e1a

File tree

10 files changed

+118
-34
lines changed

10 files changed

+118
-34
lines changed

.cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@
130130
"sockname",
131131
"spex",
132132
"ssljson",
133+
"statename",
133134
"statsd",
134135
"strftime",
135136
"stylesheet",

lib/nerves_hub/application.ex

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@ defmodule NervesHub.Application do
1515
end
1616

1717
setup_open_telemetry()
18-
19-
_ =
20-
:logger.add_handler(:my_sentry_handler, Sentry.LoggerHandler, %{
21-
config: %{metadata: [:file, :line]}
22-
})
23-
24-
NervesHub.Logger.attach()
18+
setup_logging()
2519

2620
children =
2721
[{Finch, name: Swoosh.Finch}] ++
@@ -50,6 +44,18 @@ defmodule NervesHub.Application do
5044
Supervisor.start_link(children, opts)
5145
end
5246

47+
defp setup_logging() do
48+
:ok =
49+
:logger.add_handler(:sentry_handler, Sentry.LoggerHandler, %{
50+
config: %{metadata: [:file, :line]}
51+
})
52+
53+
:ok =
54+
:logger.add_primary_filter(:filter_ssl_handshake, {&NervesHub.Logger.ssl_log_filter/2, []})
55+
56+
NervesHub.Logger.attach()
57+
end
58+
5359
defp setup_open_telemetry() do
5460
if System.get_env("ECTO_IPV6") do
5561
:ok = :httpc.set_option(:ipfamily, :inet6fb4)

lib/nerves_hub/logger.ex

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ defmodule NervesHub.Logger do
3535
[:nerves_hub, :devices, :update, :successful],
3636
[:nerves_hub, :managed_deployments, :set_deployment_group, :none_found],
3737
[:nerves_hub, :managed_deployments, :set_deployment_group, :one_found],
38-
[:nerves_hub, :managed_deployments, :set_deployment_group, :multiple_found]
38+
[:nerves_hub, :managed_deployments, :set_deployment_group, :multiple_found],
39+
[:nerves_hub, :ssl, :fail]
3940
]
4041

4142
Enum.each(events, fn event ->
@@ -165,6 +166,40 @@ defmodule NervesHub.Logger do
165166
)
166167
end
167168

169+
def log_event([:nerves_hub, :ssl, :fail], _, metadata, _) do
170+
Logger.info("SSL certificate verification failed",
171+
event: "nerves_hub.ssl.fail",
172+
reason: metadata[:reason],
173+
cert_serial: metadata[:cert_serial],
174+
cert_subject: metadata[:cert_subject]
175+
)
176+
end
177+
178+
@doc """
179+
The Erlang SSL application will log issues or failures related to verification of certificates.
180+
181+
This filter is designed to ignore SSL handshake errors that occur during the `:certify` state that are not helpful or hard to understand.
182+
183+
eg. TLS :server: In state :certify at ssl_handshake.erl:2201 generated SERVER ALERT: Fatal - Handshake Failure - :unknown_ca
184+
"""
185+
def ssl_log_filter(log_event, _opts) do
186+
case log_event do
187+
%{
188+
msg:
189+
{:report,
190+
%{
191+
alert: {:alert, _, _, %{file: ~c"ssl_handshake.erl"}, _, _},
192+
role: :server,
193+
statename: :certify
194+
}}
195+
} ->
196+
:stop
197+
198+
_ ->
199+
:ignore
200+
end
201+
end
202+
168203
# Helper functions
169204

170205
defp ignore_list() do

lib/nerves_hub/ssl.ex

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,24 +85,16 @@ defmodule NervesHub.SSL do
8585
{:valid, state}
8686

8787
{:error, {:bad_cert, reason}} ->
88-
:telemetry.execute([:nerves_hub, :ssl, :fail], %{count: 1})
89-
90-
{:fail, reason}
88+
verify_failed(reason, otp_cert)
9189

9290
{:error, _} ->
93-
:telemetry.execute([:nerves_hub, :ssl, :fail], %{count: 1})
94-
95-
{:fail, :registration_failed}
91+
verify_failed(:registration_failed, otp_cert)
9692

9793
reason when is_atom(reason) ->
98-
:telemetry.execute([:nerves_hub, :ssl, :fail], %{count: 1})
99-
100-
{:fail, reason}
94+
verify_failed(reason, otp_cert)
10195

10296
_ ->
103-
:telemetry.execute([:nerves_hub, :ssl, :fail], %{count: 1})
104-
105-
{:fail, :unknown_server_error}
97+
verify_failed(:unknown_server_error, otp_cert)
10698
end
10799
end
108100

@@ -283,4 +275,17 @@ defmodule NervesHub.SSL do
283275
ski: Certificate.get_ski(otp_cert)
284276
}
285277
end
278+
279+
defp verify_failed(reason, otp_cert) do
280+
cert_serial = Certificate.get_serial_number(otp_cert)
281+
cert_subject = Certificate.get_common_name(otp_cert)
282+
283+
:telemetry.execute([:nerves_hub, :ssl, :fail], %{count: 1}, %{
284+
reason: reason,
285+
cert_serial: cert_serial,
286+
cert_subject: cert_subject
287+
})
288+
289+
{:fail, reason}
290+
end
286291
end

lib/nerves_hub_web/channels/device_events_stream_channel.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ defmodule NervesHubWeb.DeviceEventsStreamChannel do
4848
false
4949

5050
org_user ->
51-
Authorization.authorized?(:"device:console", org_user)
51+
Authorization.authorized?(:"device:view", org_user)
5252
end
5353
end
5454
end

lib/nerves_hub_web/channels/device_socket.ex

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,17 @@ defmodule NervesHubWeb.DeviceSocket do
114114

115115
{:error, :invalid_auth}
116116
end
117+
rescue
118+
e in ArgumentError ->
119+
headers = Map.new(x_headers)
120+
121+
:telemetry.execute([:nerves_hub, :devices, :invalid_auth], %{count: 1}, %{
122+
auth: :shared_secrets,
123+
reason: e,
124+
product_key: Map.get(headers, "x-nh-key", "*empty*")
125+
})
126+
127+
{:error, :invalid_auth}
117128
end
118129

119130
def connect(_params, _socket, _connect_info) do

lib/nerves_hub_web/helpers/authorization.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ defmodule NervesHubWeb.Helpers.Authorization do
3030

3131
def authorized?(:"device:create", %OrgUser{role: role}), do: role_check(:manage, role)
3232
def authorized?(:"device:update", %OrgUser{role: role}), do: role_check(:manage, role)
33+
def authorized?(:"device:view", %OrgUser{role: role}), do: role_check(:view, role)
3334

3435
def authorized?(:"device:set-deployment-group", %OrgUser{role: role}),
3536
do: role_check(:manage, role)

0 commit comments

Comments
 (0)