Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduced fixed certificates for tests #51

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/certifi.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
-export([cacertfile/0,
cacerts/0]).

-ifdef(TEST).
-export([cacerts_test_data/0]).
-endif.

%% @doc CACertFile gives the path to the file with an X.509 certificate list
%% containing the Mozilla CA Certificate that can then be used via the
%% cacertfile setting in ssl options passed to the connect function.
Expand All @@ -29,4 +33,11 @@ cacertfile() ->
%% passed to the connect function.
-spec cacerts() -> [binary(),...].
cacerts() ->
ok.
[].

-ifdef(TEST).
%% @doc CACertsTestData provides fixed certificates for testing.
-spec cacerts_test_data() -> [binary(),...].
cacerts_test_data() ->
[].
-endif.
25 changes: 19 additions & 6 deletions src/certifi_pt.erl
Original file line number Diff line number Diff line change
@@ -1,27 +1,40 @@
-module(certifi_pt).
-export([parse_transform/2]).

%% The function replace_cacerts/1 calls public_key:pem_decode/1.
%% Dialyzer warns that public_key:pem_decode/1 is undefined because
%% the public_key application is not listed in the certifi.app.src file.
%% Since public_key is not required at runtime, we suppress this warning
%% instead of adding public_key as a dependency.
-dialyzer([{no_unknown, [replace_cacerts/1]}]).

parse_transform(Forms, _Opts) ->
[replace_cacerts(Form) || Form <- Forms].

replace_cacerts({function, Ann, cacerts, 0, [_]}) ->
{ok, Binary} = file:read_file(cert_file() ),
replace_cacerts({function, Ann, Function, 0, [_]}) when
Function =:= cacerts orelse Function =:= cacerts_test_data->
{ok, Binary} = file:read_file(cert_file(Function)),
Pems = public_key:pem_decode(Binary),
Cacerts = [Der || {'Certificate', Der, _} <- Pems],
Body = lists:foldl(fun(Cert, Acc) ->
{cons, 0, cert_to_bin_ast(Cert), Acc}
end, {nil, 0}, Cacerts),
{function, Ann, cacerts, 0, [{clause, Ann, [], [], [Body]}]};
{function, Ann, Function, 0, [{clause, Ann, [], [], [Body]}]};
replace_cacerts(Other) ->
Other.

-spec cert_file() -> Result when
-spec cert_file(Function) -> Result when
Function :: cacerts | cacerts_test_data,
Result :: file:filename_all().
cert_file() ->
cert_file(Function) ->
AppDir = filename:dirname(
filename:dirname(code:which(?MODULE))
),
filename:join([AppDir, "priv", "cacerts.pem"]).
Dir = case Function of
cacerts -> "priv";
cacerts_test_data -> "test/data"
end,
filename:join([AppDir, Dir, "cacerts.pem"]).

-spec cert_to_bin_ast(Cert) -> Result when
Cert :: binary(),
Expand Down
22 changes: 16 additions & 6 deletions test/certifi_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,27 @@

-include_lib("eunit/include/eunit.hrl").

%% Update this when updating priv/cacerts.pem.
-define(NUM_OF_CERTS, 147).
Comment on lines +5 to +6
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially, I thought this number could be generated by parsing priv/cacerts.pem.
However, I realized this approach would weaken the test because parsing the file to verify it is properly parsed sounds somewhat circular.


-ifdef('OTP_20_AND_ABOVE').
reproducible_module_test() ->
%% When compiled with +deterministic, only version is left out.
?assertMatch([{version,[_|_]}], certifi:module_info(compile)).
-endif.

cacerts_test_() ->
Certs = [Cert1, Cert2, Cert3 | _] = certifi:cacerts(),
[?_assertEqual(128, length(Certs))
,?_assertMatch(<<48,130,5,192,48,130,3,168,160,3,2,1,2,2,16,30,191,89,80,184,_/binary>>, Cert1)
,?_assertMatch(<<48,130,2,101,48,130,1,235,160,3,2,1,2,2,16,120,143,39,92,_/binary>>, Cert2)
,?_assertMatch(<<48,130,5,239,48,130,3,215,160,3,2,1,2,2,8,13,211,227,188,_/binary>>, Cert3)
,?_assertMatch(<<48,130,3,117,48,130,2,93,160,3,2,1,2,2,11,4,0,0,0,0,1,21,75,90,195,148,48,13,6,_/binary>>, lists:last(Certs))
%% Checking the contents is difficult because they change frequently.
%% Therefore, this test only checks the number and type of certificates.
Certs = certifi:cacerts(),
[?_assertEqual(?NUM_OF_CERTS, length(Certs))
,?_assert(lists:all(fun is_binary/1, Certs))
].

cacerts_test_data_test_() ->
Certs = [Cert1, Cert2, Cert3] = certifi:cacerts_test_data(),
[?_assertEqual(3, length(Certs))
,?_assertMatch(<<48,130,3,199,48,130,2,175,160,3,2,1,2,2,20,46,59,44,50,129,_/binary>>, Cert1)
,?_assertMatch(<<48,130,3,199,48,130,2,175,160,3,2,1,2,2,20,22,71,8,124,36,_/binary>>, Cert2)
,?_assertMatch(<<48,130,3,199,48,130,2,175,160,3,2,1,2,2,20,39,199,152,45,116,_/binary>>, Cert3)
].
71 changes: 71 additions & 0 deletions test/data/cacerts.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
-----BEGIN CERTIFICATE-----
MIIDxzCCAq+gAwIBAgIUJ8eYLXRZClJruoSCfyQr/0phTOMwDQYJKoZIhvcNAQEL
BQAwcjELMAkGA1UEBhMCWFgxDTALBgNVBAgMBEJFQU0xDzANBgNVBAcMBkVybGFu
ZzEWMBQGA1UECgwNRXJsYW5nQ2VydGlmaTERMA8GA1UECwwIVW5pdFRlc3QxGDAW
BgNVBAMMD0NBQ2VydFRlc3REYXRhMTAgFw0yNDA1MjYwMjU3MjVaGA8yMTI0MDUw
MjAyNTcyNVowcjELMAkGA1UEBhMCWFgxDTALBgNVBAgMBEJFQU0xDzANBgNVBAcM
BkVybGFuZzEWMBQGA1UECgwNRXJsYW5nQ2VydGlmaTERMA8GA1UECwwIVW5pdFRl
c3QxGDAWBgNVBAMMD0NBQ2VydFRlc3REYXRhMTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAJlSHRxjQvZrnO4UnbgPaiXHDPkxossCBWpz9/U3ZEFnvT3j
j0vMAdEmWtH+2Q9J/2OtEzWwpkcpr7IrhNdIiLLK9WJA2RzZSiVj3Cczf7tLcAxL
Jd+x9cyRi/olKXONOU0in27BxK5krM+kawBB7OPA9iCZ2OowRwh7h/WhbuSjDvfs
jBvOYDl5S1cRWnHvY0IccDjqd+HpwonOM8dK+RxFz1J2NbFJUhJRJ65GAntSAYXM
FF9ad4t7oeFYdCWmdqeFTYyhB5GEDD+57XNUlK1XH64ekBHoD2Zathndl0Xo817w
0V5nTZuqZZVjHzYPAB7Sefl6UkKzIQpw3PVotj8CAwEAAaNTMFEwHQYDVR0OBBYE
FPpgdokCaVn6K8eW/V/V57c9LuI+MB8GA1UdIwQYMBaAFPpgdokCaVn6K8eW/V/V
57c9LuI+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAQZKsgt
hT/dHomlNGEc/Z92O8pSKnqFNrrdToAlsXRwDc4LAOeOJOu2WKvKWc8za3jYk+S3
giiLRghnjbztX/WaZofjGQOhlSQeTUVXBSd9hGZv6MDC0Ug/oJYZ9jvmVxjJpiac
qOf461R3PVayo8hVjZe6z0G4Z0Rfq/HnZ3pZU9HV5+wMJ7/wQBq7E0o0kW4tlX9G
U2Wn4gZbu9FimVoS1kfpYYtBSRCpvVlj0lxjDQLXtAq4F0nokR/MZb55Wkm1YA+i
6v0Ec+UQ+cYTEEProIM9IjiOCZxLJ3DdAFa95fTbsWqyPp2h+ZrmujqNlZ8K8d8h
eKGL33vz11++ozQ=
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
MIIDxzCCAq+gAwIBAgIUFkcIfCRoKId9e4a2eU/p1h8YLxgwDQYJKoZIhvcNAQEL
BQAwcjELMAkGA1UEBhMCWFgxDTALBgNVBAgMBEJFQU0xDzANBgNVBAcMBkVybGFu
ZzEWMBQGA1UECgwNRXJsYW5nQ2VydGlmaTERMA8GA1UECwwIVW5pdFRlc3QxGDAW
BgNVBAMMD0NBQ2VydFRlc3REYXRhMjAgFw0yNDA1MjYwMjU3NDVaGA8yMTI0MDUw
MjAyNTc0NVowcjELMAkGA1UEBhMCWFgxDTALBgNVBAgMBEJFQU0xDzANBgNVBAcM
BkVybGFuZzEWMBQGA1UECgwNRXJsYW5nQ2VydGlmaTERMA8GA1UECwwIVW5pdFRl
c3QxGDAWBgNVBAMMD0NBQ2VydFRlc3REYXRhMjCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAK/6T2WlAH86DQ/J1rLuRXt+1He9ye9nTa23u8jTcBP2ilIj
HWCqNkhaG+kYW5uiTvz+TCBCM+uOJGQ17dzQfwiky4PP0qbm02WTxgy51nMPYfyc
rJ4l6M/XWkrRz7gtr+iaefdKcT8+T1Oejo2Sk+JcVoAfsFAzgoiv8D0/ilI3BMRz
ia9dCLVQH/dBgXkHuogaeQfnACIf2MBf9eBYJk9+TDgOgRQbp4kpovst6wCopazS
2P2+4zyKWn6Lqqllc3hovB3DxerIDuFOXxsF7ZgXMyBrw4lWlXnfZ1nWT6KQ+Su1
UaEgrCrT/zEa4vv73456K4POTB7hPnoKIbjY8zcCAwEAAaNTMFEwHQYDVR0OBBYE
FNib8+GDQ6H/++tkS52rVHlZlmY9MB8GA1UdIwQYMBaAFNib8+GDQ6H/++tkS52r
VHlZlmY9MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKEJ8D10
rXBJchkwHtj9FdDukLZthnp+NUniYkQTvFm3a7Xw6z6kAdlwLZ5rgp6qRQc1Fumr
MA9YMmp0Y9VyTdyHTrykTWgdEKRd1hn/v1Rsoh96g6zOphE8BSBl/2Z9k3AOMl3p
qWwrAzgOEWxdYrkUpicTGrbocKiVm5YBYryMeB1r+UDQ8uJDOlhYjUg9Zmm0yTyf
b4N9U5qxZvTpxv/msxD8woxhiO6AATg5hNX2Ed2wPUECbUMre7hL4QKrT6J435Qm
XOHz5C72QNy3Hz0gUFJdRhR8IwW8gi8pXQooqu5AmzuqllVmNF29CriSBplhjoND
8SKQlVZBs51f8E0=
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
MIIDxzCCAq+gAwIBAgIULjssMoENyVlErmdM909t9a8TPEkwDQYJKoZIhvcNAQEL
BQAwcjELMAkGA1UEBhMCWFgxDTALBgNVBAgMBEJFQU0xDzANBgNVBAcMBkVybGFu
ZzEWMBQGA1UECgwNRXJsYW5nQ2VydGlmaTERMA8GA1UECwwIVW5pdFRlc3QxGDAW
BgNVBAMMD0NBQ2VydFRlc3REYXRhMzAgFw0yNDA1MjYwMjU3NTRaGA8yMTI0MDUw
MjAyNTc1NFowcjELMAkGA1UEBhMCWFgxDTALBgNVBAgMBEJFQU0xDzANBgNVBAcM
BkVybGFuZzEWMBQGA1UECgwNRXJsYW5nQ2VydGlmaTERMA8GA1UECwwIVW5pdFRl
c3QxGDAWBgNVBAMMD0NBQ2VydFRlc3REYXRhMzCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAJZ+C5Z1n6dHs2dCmV7jm/Yi+48BFU4Esky5fX+wcwJ/oWZn
BPCOTJpBJ03+23Smsexyxr5Ybf7YMBOMrP1+A1l7S3XTFWViofds+dQTT8KOaZBU
KsVdZfFyjHsojS7RZ44iMziO6iUUwaFYG3DDAwU3N8DOYqJhEm4I5C+vkc65sJSh
b0IqdQ4QX17c5zKY+jUpeDxraCIwpIRaNHuIS6CfG1n1NUv9PqHPigRlTlQYHCdj
vmOhl2VnIHqnWpBt6VQWXibbUF/D48MBcYf9oZH7xBEtUwPalTDK/v19RmWxnCMh
Rck1YbCqCunxAR/YhqikfBbbO6YTJqVHkmhc388CAwEAAaNTMFEwHQYDVR0OBBYE
FMcwbk5r9achU5j8ij2ESXZJqMyMMB8GA1UdIwQYMBaAFMcwbk5r9achU5j8ij2E
SXZJqMyMMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABCQECeb
vLkQlLcKaNu57ccaiwyKOKl9PRZIjCy43lhVVe6ida837XUPOANR7bH54oPCq9Yp
ElV0IwE3SBoxBElhFqB0iL78wFw4OMQMmQOe1R8tAmGI0GZRs5P+wM+7PsXELy8f
bvfHyLK1JDwFMeZ63NIVlwkJfGkQOQljGhTPDvyEszGNc2nEEZo4dLaCBjeuLtHo
gG+e6lI3jxZuphBXW6AUlOmJQWhk9pRlE4Cj5lU+R8Cb24QxRWneXdn3vpX974zc
rrvErTtrQjFNdvkAKINZzJgukXzYaRKQ8N2ULqD2xtJ6YkOgBQEHqBIowxSdKvHD
lrO3tTA5Ejr4Udg=
-----END CERTIFICATE-----