From 8c6cd69caa6dffacd4552ed8f7fac1bce17aa903 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Thu, 4 Jul 2024 14:30:04 +0800 Subject: [PATCH 1/2] fix: obtain cert expiry epoch failed due to formated `generalTime` --- .../src/emqx_prometheus.app.src | 2 +- apps/emqx_prometheus/src/emqx_prometheus.erl | 26 +++++++------------ changes/fix-13412.en.md | 1 + 3 files changed, 12 insertions(+), 17 deletions(-) create mode 100644 changes/fix-13412.en.md diff --git a/apps/emqx_prometheus/src/emqx_prometheus.app.src b/apps/emqx_prometheus/src/emqx_prometheus.app.src index 713a3e511..e5bb770cd 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus.app.src +++ b/apps/emqx_prometheus/src/emqx_prometheus.app.src @@ -2,7 +2,7 @@ {application, emqx_prometheus, [ {description, "Prometheus for EMQX"}, % strict semver, bump manually! - {vsn, "5.2.2"}, + {vsn, "5.2.3"}, {modules, []}, {registered, [emqx_prometheus_sup]}, {applications, [kernel, stdlib, prometheus, emqx, emqx_auth, emqx_resource, emqx_management]}, diff --git a/apps/emqx_prometheus/src/emqx_prometheus.erl b/apps/emqx_prometheus/src/emqx_prometheus.erl index f4d0ff2c0..fd2faf11a 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus.erl @@ -944,9 +944,7 @@ cert_expiry_at_from_path(Path0) -> [CertEntry | _] = public_key:pem_decode(PemBin), Cert = public_key:pem_entry_decode(CertEntry), %% TODO: Not fully tested for all certs type - {'utcTime', NotAfterUtc} = - Cert#'Certificate'.'tbsCertificate'#'TBSCertificate'.validity#'Validity'.'notAfter', - utc_time_to_epoch(NotAfterUtc); + not_after_epoch(Cert); {error, Reason} -> ?SLOG(error, #{ msg => "read_cert_file_failed", @@ -969,21 +967,17 @@ cert_expiry_at_from_path(Path0) -> 0 end. -utc_time_to_epoch(UtcTime) -> - date_to_expiry_epoch(utc_time_to_datetime(UtcTime)). - -utc_time_to_datetime(Str) -> - {ok, [Year, Month, Day, Hour, Minute, Second], _} = io_lib:fread( - "~2d~2d~2d~2d~2d~2dZ", Str - ), - %% Always Assuming YY is in 2000 - {{2000 + Year, Month, Day}, {Hour, Minute, Second}}. - %% 62167219200 =:= calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}). -define(EPOCH_START, 62167219200). --spec date_to_expiry_epoch(calendar:datetime()) -> Seconds :: non_neg_integer(). -date_to_expiry_epoch(DateTime) -> - calendar:datetime_to_gregorian_seconds(DateTime) - ?EPOCH_START. +not_after_epoch(#'Certificate'{ + 'tbsCertificate' = #'TBSCertificate'{ + validity = + #'Validity'{'notAfter' = NotAfter} + } +}) -> + pubkey_cert:'time_str_2_gregorian_sec'(NotAfter) - ?EPOCH_START; +not_after_epoch(_) -> + 0. %%======================================== %% Mria diff --git a/changes/fix-13412.en.md b/changes/fix-13412.en.md new file mode 100644 index 000000000..0afc6cceb --- /dev/null +++ b/changes/fix-13412.en.md @@ -0,0 +1 @@ +Fixed an issue in the Prometheus API where the certificate expiration time format incorrectly returned `0` due to the use of `generalTime`. From d84d31cbc572f0b00856ed646fcfa1cac714b351 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Thu, 4 Jul 2024 18:18:13 +0800 Subject: [PATCH 2/2] test: cert expiry epoch with `generalTime` formatted --- apps/emqx_prometheus/.gitignore | 1 - apps/emqx_prometheus/src/emqx_prometheus.erl | 6 +++++- apps/emqx_prometheus/test/data/cert.crt | 21 +++++++++++++++++++ .../test/emqx_prometheus_SUITE.erl | 14 +++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 apps/emqx_prometheus/test/data/cert.crt diff --git a/apps/emqx_prometheus/.gitignore b/apps/emqx_prometheus/.gitignore index b89cbebfd..233b9f887 100644 --- a/apps/emqx_prometheus/.gitignore +++ b/apps/emqx_prometheus/.gitignore @@ -13,7 +13,6 @@ rel/example_project emqx_prometheus.d ct.coverdata logs/ -data/ test/ct.cover.spec cover/ erlang.mk diff --git a/apps/emqx_prometheus/src/emqx_prometheus.erl b/apps/emqx_prometheus/src/emqx_prometheus.erl index fd2faf11a..1474164f6 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus.erl @@ -78,6 +78,10 @@ do_stop/0 ]). +-ifdef(TEST). +-export([cert_expiry_at_from_path/1]). +-endif. + %%-------------------------------------------------------------------- %% Macros %%-------------------------------------------------------------------- @@ -943,7 +947,7 @@ cert_expiry_at_from_path(Path0) -> {ok, PemBin} -> [CertEntry | _] = public_key:pem_decode(PemBin), Cert = public_key:pem_entry_decode(CertEntry), - %% TODO: Not fully tested for all certs type + %% XXX: Only pem cert supported by listeners not_after_epoch(Cert); {error, Reason} -> ?SLOG(error, #{ diff --git a/apps/emqx_prometheus/test/data/cert.crt b/apps/emqx_prometheus/test/data/cert.crt new file mode 100644 index 000000000..6f09b5609 --- /dev/null +++ b/apps/emqx_prometheus/test/data/cert.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfzCCAmegAwIBAgIUJ3pE/Dwffa5gKNHY2L8HmazicmowDQYJKoZIhvcNAQEL +BQAwZzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM +DVNhbiBGcmFuY2lzY28xFTATBgNVBAoMDEV4YW1wbGUgSW5jLjEUMBIGA1UEAwwL +ZXhhbXBsZS5jb20wIBcNMjQwNzAzMTAyOTMzWhgPMjA1NDA2MjYxMDI5MzNaMGcx +CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4g +RnJhbmNpc2NvMRUwEwYDVQQKDAxFeGFtcGxlIEluYy4xFDASBgNVBAMMC2V4YW1w +bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArFZKxzsxCaGP +rVhilTd4PKk9jVrBLQ4xaFG6tmmlzjBCp+E35EulND4gpWZSUs9bYO/C+qykKmrL +J7TddGBVXe6lbl6mMHqZzHUp9mJdvPBSHcqOHc2E/UiBwOpN4tatx6UdK+VEQySr +z+dtc0Az5Itkoy/SvAu1Zzdq3d3MfxaTUvCmWfeR2huTalNQkG1jQ0C2CjCU9Z1f +Ex+y1MzxNhVrrdExC8Vwrb4TDlue8/XwJ4A4gBJYNbVAwALcSKnF56nRib3evE3J +Irvy2Rt4aC694JawWLPzJ1e2Rz8WBzCRPJAmaV4iD66sU8BMkmbCV+mMmF673s3R +sS4kGqklvQIDAQABoyEwHzAdBgNVHQ4EFgQU0tDKnCDey6fKrzs7caDfS41Dii4w +DQYJKoZIhvcNAQELBQADggEBAEIKvrSuUgpkIEUDV+UMr/5xUKkDyjNi4rwkBA6X +Ej0HskXg6u9wOIkBKwpQbleDFICdyqXMhGMjN4050PQCizaInBJBz77ah47UwGGQ +P+wavbcdHR9cbhewhCo6EtbCclPY1LXq4OFkgHMToLFzXC4S/kLX/KrhVApGHskO +Ad4U4gmMtIalruz5Mzc4YuSaAjbRI9v0IxhvS8JU0uoOwhIstkrMlFc26SU6EcZ9 +k88gVmmqEnsvmJi4gn4XPgvJB8hPs0/OMDBCVjAM8VaxZZ6sqlTT9FTGaKbIJdDc +KjT7VdbhVcuZo4s1u9gQzJNU2WHlHLwZi1wCjTC1vTE/HrQ= +-----END CERTIFICATE----- diff --git a/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl b/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl index c97913ec2..dd125f97b 100644 --- a/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl +++ b/apps/emqx_prometheus/test/emqx_prometheus_SUITE.erl @@ -211,6 +211,16 @@ t_push_gateway(_) -> ok. +t_cert_expiry_epoch(_) -> + Path = some_pem_path(), + ?assertEqual( + 2666082573, + emqx_prometheus:cert_expiry_at_from_path(Path) + ). + +%%-------------------------------------------------------------------- +%% Helper functions + start_mock_pushgateway(Port) -> ensure_loaded(cowboy), ensure_loaded(ranch), @@ -249,3 +259,7 @@ init(Req0, Opts) -> RespHeader = #{<<"content-type">> => <<"text/plain; charset=utf-8">>}, Req = cowboy_req:reply(200, RespHeader, <<"OK">>, Req0), {ok, Req, Opts}. + +some_pem_path() -> + Dir = code:lib_dir(emqx_prometheus, test), + _Path = filename:join([Dir, "data", "cert.crt"]).