laforge submitted this change.

View Change

Approvals: fixeria: Looks good to me, but someone else must approve laforge: Looks good to me, approved Jenkins Builder: Verified
certificates: fix certificate location, make sure cert/key files are readable

The certificate and key files are placed in the config directory. This is
an unfortunate location, since it causes a lot of trouble when referencing
those files.

The erlang documentation suggests to place so called auxillary files in a
"priv" directory on the same level as the config directory. The path to
the priv directory can then be located using code:priv_dir.

see also: https://www.erlang.org/docs/26/design_principles/applications.html

Let's adopt this mechanism by adding utility functions that allow us to
resolve the file paths to files inside the priv directory. Let's also
automatically check if the referenced file is readable, so that we get
a proper error in the log in case a certificate or key file is missing

Change-Id: Ie09d746a6e28ac6fee3e00dfa32cb01f8a7b947e
Related: SYS#7093
---
M config/sys.config
R priv/sample_eim_cert_brainpool.crt
R priv/sample_eim_cert_brainpool.key
R priv/sample_eim_cert_nist.crt
R priv/sample_eim_cert_nist.key
R priv/sample_ssl_cert.crt
R priv/sample_ssl_cert.key
R priv/sgp26_gsma_root_ci_cert_nist_oiste.crt
R priv/sgp26_gsma_root_ci_cert_nist_symantec.crt
R priv/sgp26_test_root_ci_cert_brainpool.crt
R priv/sgp26_test_root_ci_cert_nist.crt
M src/crypto_utils.erl
M src/eim_cfg.erl
M src/onomondo_eim_app.erl
M src/rest_handler.erl
M src/utils.erl
16 files changed, 44 insertions(+), 22 deletions(-)

diff --git a/config/sys.config b/config/sys.config
index 990a442..81c438c 100644
--- a/config/sys.config
+++ b/config/sys.config
@@ -3,24 +3,24 @@
{esipa_ip, {127, 0, 0, 1}},
{esipa_port, 8000},
{esipa_ssl_disable, false},
- {esipa_ssl_cert, "config/sample_ssl_cert.crt"},
- {esipa_ssl_key, "config/sample_ssl_cert.key"},
+ {esipa_ssl_cert, "sample_ssl_cert.crt"},
+ {esipa_ssl_key, "sample_ssl_cert.key"},
{rest_ip, {127, 0, 0, 1}},
{rest_port, 8080},
{eim_id, "eIM"},
{es9p_ssl_disable, false},
- {eim_cert, "config/sample_eim_cert_nist.crt"},
- {eim_key, "config/sample_eim_cert_nist.key"},
+ {eim_cert, "sample_eim_cert_nist.crt"},
+ {eim_key, "sample_eim_cert_nist.key"},
{counter_value, 1},
{consumer_euicc, true},
{rest_timeout_stuck, 300},
{rest_timeout_noshow, 1800},
{rest_timeout_expired, 86400},
{root_ci_certs, [
- "config/sgp26_gsma_root_ci_cert_nist_symantec.crt",
- "config/sgp26_gsma_root_ci_cert_nist_oiste.crt",
- "config/sgp26_test_root_ci_cert_nist.crt",
- "config/sgp26_test_root_ci_cert_brainpool.crt"
+ "sgp26_gsma_root_ci_cert_nist_symantec.crt",
+ "sgp26_gsma_root_ci_cert_nist_oiste.crt",
+ "sgp26_test_root_ci_cert_nist.crt",
+ "sgp26_test_root_ci_cert_brainpool.crt"
]}
]}
].
diff --git a/config/sample_eim_cert_brainpool.crt b/priv/sample_eim_cert_brainpool.crt
similarity index 100%
rename from config/sample_eim_cert_brainpool.crt
rename to priv/sample_eim_cert_brainpool.crt
diff --git a/config/sample_eim_cert_brainpool.key b/priv/sample_eim_cert_brainpool.key
similarity index 100%
rename from config/sample_eim_cert_brainpool.key
rename to priv/sample_eim_cert_brainpool.key
diff --git a/config/sample_eim_cert_nist.crt b/priv/sample_eim_cert_nist.crt
similarity index 100%
rename from config/sample_eim_cert_nist.crt
rename to priv/sample_eim_cert_nist.crt
diff --git a/config/sample_eim_cert_nist.key b/priv/sample_eim_cert_nist.key
similarity index 100%
rename from config/sample_eim_cert_nist.key
rename to priv/sample_eim_cert_nist.key
diff --git a/config/sample_ssl_cert.crt b/priv/sample_ssl_cert.crt
similarity index 100%
rename from config/sample_ssl_cert.crt
rename to priv/sample_ssl_cert.crt
diff --git a/config/sample_ssl_cert.key b/priv/sample_ssl_cert.key
similarity index 100%
rename from config/sample_ssl_cert.key
rename to priv/sample_ssl_cert.key
diff --git a/config/sgp26_gsma_root_ci_cert_nist_oiste.crt b/priv/sgp26_gsma_root_ci_cert_nist_oiste.crt
similarity index 100%
rename from config/sgp26_gsma_root_ci_cert_nist_oiste.crt
rename to priv/sgp26_gsma_root_ci_cert_nist_oiste.crt
diff --git a/config/sgp26_gsma_root_ci_cert_nist_symantec.crt b/priv/sgp26_gsma_root_ci_cert_nist_symantec.crt
similarity index 100%
rename from config/sgp26_gsma_root_ci_cert_nist_symantec.crt
rename to priv/sgp26_gsma_root_ci_cert_nist_symantec.crt
diff --git a/config/sgp26_test_root_ci_cert_brainpool.crt b/priv/sgp26_test_root_ci_cert_brainpool.crt
similarity index 100%
rename from config/sgp26_test_root_ci_cert_brainpool.crt
rename to priv/sgp26_test_root_ci_cert_brainpool.crt
diff --git a/config/sgp26_test_root_ci_cert_nist.crt b/priv/sgp26_test_root_ci_cert_nist.crt
similarity index 100%
rename from config/sgp26_test_root_ci_cert_nist.crt
rename to priv/sgp26_test_root_ci_cert_nist.crt
diff --git a/src/crypto_utils.erl b/src/crypto_utils.erl
index 9d0cd0f..aca40e9 100644
--- a/src/crypto_utils.erl
+++ b/src/crypto_utils.erl
@@ -51,7 +51,7 @@
]),

%Load private key from eIM certificate
- {ok, EimKeyPath} = application:get_env(onomondo_eim, eim_key),
+ {ok, EimKeyPath} = utils:get_env_priv_file_path(onomondo_eim, eim_key),
{ok, EimKeyPem} = file:read_file(EimKeyPath),
[EimKeyPemEntry] = public_key:pem_decode(EimKeyPem),
EimKeyECPrivateKey = public_key:pem_entry_decode(EimKeyPemEntry),
@@ -209,8 +209,9 @@
]
),
error;
-get_root_cert(EumCertificate, RootCiCertPaths) ->
- [RootCiCertPath | RootCiCertPathsTail] = RootCiCertPaths,
+get_root_cert(EumCertificate, RootCiCerts) ->
+ [RootCiCert | RootCiCertsTail] = RootCiCerts,
+ {ok, RootCiCertPath} = utils:get_priv_file_path(onomondo_eim, RootCiCert),
{ok, RootCiCertPem} = file:read_file(RootCiCertPath),
[{'Certificate', RootCiCertBer, not_encrypted}] = public_key:pem_decode(RootCiCertPem),
{ok, EumCertificateBer} = 'PKIX1Explicit88':encode('Certificate', EumCertificate),
@@ -218,12 +219,12 @@
true ->
{ok, RootCiCertPem};
_ ->
- get_root_cert(EumCertificate, RootCiCertPathsTail)
+ get_root_cert(EumCertificate, RootCiCertsTail)
end.

verify_euicc_cert(EumCertificate, EuiccCertificate) ->
- {ok, RootCiCertPaths} = application:get_env(onomondo_eim, root_ci_certs),
- case get_root_cert(EumCertificate, RootCiCertPaths) of
+ {ok, RootCiCerts} = application:get_env(onomondo_eim, root_ci_certs),
+ case get_root_cert(EumCertificate, RootCiCerts) of
{ok, RootCiCertPem} ->
[{'Certificate', RootCiCertBer, not_encrypted}] = public_key:pem_decode(RootCiCertPem),
{ok, RootCiCert} = 'PKIX1Explicit88':decode('Certificate', RootCiCertBer),
diff --git a/src/eim_cfg.erl b/src/eim_cfg.erl
index 6872461..f74ccd8 100644
--- a/src/eim_cfg.erl
+++ b/src/eim_cfg.erl
@@ -13,7 +13,7 @@
{ok, EimId} = application:get_env(onomondo_eim, eim_id),
{ok, EsipaIp} = application:get_env(onomondo_eim, esipa_ip),
{ok, EsipaPort} = application:get_env(onomondo_eim, esipa_port),
- {ok, EimCertPath} = application:get_env(onomondo_eim, eim_cert),
+ {ok, EimCertPath} = utils:get_env_priv_file_path(onomondo_eim, eim_cert),
{ok, EimCertPem} = file:read_file(EimCertPath),
[{'Certificate', EimCertBer, not_encrypted}] = public_key:pem_decode(EimCertPem),
{ok, EimCert} = 'PKIX1Explicit88':decode('Certificate', EimCertBer),
diff --git a/src/onomondo_eim_app.erl b/src/onomondo_eim_app.erl
index 5394ef5..97ed197 100644
--- a/src/onomondo_eim_app.erl
+++ b/src/onomondo_eim_app.erl
@@ -30,6 +30,7 @@
"Starting ESipa HTTPs server at ~p:~p...~ncertificate: ~p~nkey: ~p~n",
[Ip, Port, Cert, Key]
),
+
cowboy:start_tls(
https_listener_esipa,
[
@@ -104,8 +105,8 @@
{ok, EsipaIp} = application:get_env(onomondo_eim, esipa_ip),
{ok, EsipaPort} = application:get_env(onomondo_eim, esipa_port),
{ok, EsipaSslDisable} = application:get_env(onomondo_eim, esipa_ssl_disable),
- {ok, EsipaSslCert} = application:get_env(onomondo_eim, esipa_ssl_cert),
- {ok, EsipaSslKey} = application:get_env(onomondo_eim, esipa_ssl_key),
+ {ok, EsipaSslCert} = utils:get_env_priv_file_path(onomondo_eim, esipa_ssl_cert),
+ {ok, EsipaSslKey} = utils:get_env_priv_file_path(onomondo_eim, esipa_ssl_key),
{ok, _} = start_esipa_server(
EsipaSslDisable,
EsipaIp,
diff --git a/src/rest_handler.erl b/src/rest_handler.erl
index e4a24e9..db3f048 100644
--- a/src/rest_handler.erl
+++ b/src/rest_handler.erl
@@ -167,18 +167,19 @@
{ok, EsipaPort} = application:get_env(onomondo_eim, esipa_port),
{ok, Hostname} = inet:gethostname(),
{ok, Vsn} = application:get_key(onomondo_eim, vsn),
- {ok, EsipaSslCertPath} = application:get_env(onomondo_eim, esipa_ssl_cert),
+ {ok, EsipaSslCertPath} = utils:get_env_priv_file_path(onomondo_eim, esipa_ssl_cert),
{ok, EsipaSslCertPem} = file:read_file(EsipaSslCertPath),
- {ok, EimCertPath} = application:get_env(onomondo_eim, eim_cert),
+ {ok, EimCertPath} = utils:get_env_priv_file_path(onomondo_eim, eim_cert),
{ok, EimCertPem} = file:read_file(EimCertPath),
{ok, CounterValue} = application:get_env(onomondo_eim, counter_value),
{ok, ConsumerEuicc} = application:get_env(onomondo_eim, consumer_euicc),
- FormatRootCiCert = fun(RootCiCertPath) ->
+ FormatRootCiCert = fun(RootCiCert) ->
+ {ok, RootCiCertPath} = utils:get_priv_file_path(onomondo_eim, RootCiCert),
{ok, RootCiCertPem} = file:read_file(RootCiCertPath),
RootCiCertPem
end,
{ok, RootCiCerts} = application:get_env(onomondo_eim, root_ci_certs),
- RootCiCertsJson = [FormatRootCiCert(RootCiCertPath) || RootCiCertPath <- RootCiCerts],
+ RootCiCertsJson = [FormatRootCiCert(RootCiCert) || RootCiCert <- RootCiCerts],

InfoList =
{[
diff --git a/src/utils.erl b/src/utils.erl
index a71395b..d46dc2a 100644
--- a/src/utils.erl
+++ b/src/utils.erl
@@ -5,7 +5,8 @@
% Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH

-module(utils).
--export([binary_to_hex/1, hex_to_binary/1, join_binary_list/1, integer_to_bytes/1, lpad_binary/3]).
+-export([binary_to_hex/1, hex_to_binary/1, join_binary_list/1, integer_to_bytes/1, lpad_binary/3,
+ get_priv_file_path/2, get_env_priv_file_path/2]).

% Converts a single hex digit (e.g. <<"A">>) into its integer representation.
hexstr_digit_to_int(HexDigit) ->
@@ -87,3 +88,21 @@
BinaryPadded = <<Padding/binary, Binary/binary>>,
lpad_binary(BinaryPadded, Padding, Length)
end.
+
+% Get the full path for a file (from filename) located in the priv directory, make sure that the file is readable.
+get_priv_file_path(Application, Filename) ->
+ PrivDir = code:priv_dir(Application),
+ FilePath = filename:join(PrivDir, Filename),
+ case filelib:is_file(FilePath) of
+ true ->
+ {ok, FilePath};
+ _ ->
+ logger:error("file not found: ~s~n", [FilePath]),
+ error
+ end.
+
+% Get the full path for a file (from filename in sys.config environment variable) located in the priv directory,
+% make sure that the file is readable.
+get_env_priv_file_path(Application, Par) ->
+ {ok, Filename} = application:get_env(Application, Par),
+ get_priv_file_path(Application, Filename).

To view, visit change 42830. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: merged
Gerrit-Project: onomondo-eim
Gerrit-Branch: master
Gerrit-Change-Id: Ie09d746a6e28ac6fee3e00dfa32cb01f8a7b947e
Gerrit-Change-Number: 42830
Gerrit-PatchSet: 4
Gerrit-Owner: dexter <pmaier@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de>
Gerrit-Reviewer: jolly <andreas@eversberg.eu>
Gerrit-Reviewer: laforge <laforge@osmocom.org>