1 #include <gtest/gtest.h> 3 #include <boost/format.hpp> 5 #include "cert_provider_test.h" 6 #include "crypto/crypto.h" 7 #include "libaktualizr/config.h" 8 #include "utilities/utils.h" 10 static boost::filesystem::path CERT_PROVIDER_PATH;
17 const std::string test_dir;
18 const std::string fleet_ca_cert =
"tests/test_data/CAcert.pem";
19 const std::string fleet_ca_private_key =
"tests/test_data/CApkey.pem";
24 Cert(
const std::string& cert_file_path) {
25 fp_ = fopen(cert_file_path.c_str(),
"r");
27 throw std::invalid_argument(
"Cannot open the specified cert file: " + cert_file_path);
30 cert_ = PEM_read_X509(fp_, NULL, NULL, NULL);
33 throw std::runtime_error(
"Failed to read the cert file: " + cert_file_path);
42 std::string getSubjectItemValue(
int itemID) {
43 const uint32_t SUBJECT_ITEM_MAX_LENGTH = 2048;
44 char buffer[SUBJECT_ITEM_MAX_LENGTH + 1] = {0};
46 X509_NAME* subj = X509_get_subject_name(cert_);
47 if (subj ==
nullptr) {
48 throw std::runtime_error(
"Failed to retrieve a subject from the certificate");
51 if (X509_NAME_get_text_by_NID(subj, itemID, buffer, SUBJECT_ITEM_MAX_LENGTH) == -1) {
52 throw std::runtime_error(
"Failed to retrieve an item from from the certificate subject");
90 args.fleetCA = test_args_.fleet_ca_cert;
91 args.fleetCAKey = test_args_.fleet_ca_private_key;
92 args.localDir = test_args_.test_dir;
94 device_cred_gen_.run(args);
95 ASSERT_EQ(device_cred_gen_.lastExitCode(), 0) << device_cred_gen_.lastStdErr();
99 ASSERT_TRUE(boost::filesystem::exists(device_cred_path.privateKeyFileFullPath))
100 << device_cred_path.privateKeyFileFullPath;
101 ASSERT_TRUE(boost::filesystem::exists(device_cred_path.certFileFullPath)) << device_cred_path.certFileFullPath;
103 Process openssl(
"/usr/bin/openssl");
105 openssl.run({
"rsa",
"-in", device_cred_path.privateKeyFileFullPath.string(),
"-noout",
"-check"});
106 ASSERT_EQ(openssl.lastExitCode(), 0) << openssl.lastStdErr();
107 ASSERT_EQ(openssl.lastStdOut(),
"RSA key ok\n") << openssl.lastStdOut();
109 openssl.run({
"x509",
"-in", device_cred_path.certFileFullPath.string(),
"-noout",
"-pubkey"});
110 ASSERT_EQ(openssl.lastExitCode(), 0) << openssl.lastStdErr();
111 ASSERT_NE(openssl.lastStdOut().find(
"-----BEGIN PUBLIC KEY-----\n"), std::string::npos) << openssl.lastStdOut();
113 openssl.run({
"rsa",
"-in", device_cred_path.privateKeyFileFullPath.string(),
"-noout",
"-modulus"});
114 ASSERT_EQ(openssl.lastExitCode(), 0) << openssl.lastStdErr();
115 const std::string private_key_modulus = openssl.lastStdOut();
117 openssl.run({
"x509",
"-in", device_cred_path.certFileFullPath.string(),
"-noout",
"-modulus"});
118 ASSERT_EQ(openssl.lastExitCode(), 0) << openssl.lastStdErr();
119 const std::string public_key_modulus = openssl.lastStdOut();
121 ASSERT_EQ(private_key_modulus, public_key_modulus);
123 openssl.run({
"verify",
"-verbose",
"-CAfile", test_args_.fleet_ca_cert, device_cred_path.certFileFullPath.string()});
124 ASSERT_EQ(openssl.lastExitCode(), 0) << openssl.lastStdErr();
125 ASSERT_EQ(openssl.lastStdOut(), str(boost::format(
"%1%: OK\n") % device_cred_path.certFileFullPath.string()));
141 const std::string expected_error_msg =
"fleet-ca and fleet-ca-key options should be used together\n";
146 args.fleetCA = test_args_.fleet_ca_cert;
148 args.localDir = test_args_.test_dir;
150 device_cred_gen_.run(args);
152 EXPECT_EQ(device_cred_gen_.lastExitCode(), 1) << device_cred_gen_.lastStdOut();
153 ASSERT_EQ(device_cred_gen_.lastStdErr(), expected_error_msg) << device_cred_gen_.lastStdErr();
160 args.fleetCAKey = test_args_.fleet_ca_private_key;
161 args.localDir = test_args_.test_dir;
163 device_cred_gen_.run(args);
165 EXPECT_EQ(device_cred_gen_.lastExitCode(), 1) << device_cred_gen_.lastStdOut();
166 ASSERT_EQ(device_cred_gen_.lastStdErr(), expected_error_msg) << device_cred_gen_.lastStdErr();
172 args.fleetCA = test_args_.fleet_ca_cert;
173 args.fleetCAKey = test_args_.fleet_ca_private_key;
176 device_cred_gen_.run(args);
178 ASSERT_EQ(device_cred_gen_.lastExitCode(), 1);
179 ASSERT_NE(device_cred_gen_.lastStdErr().find(
180 "Please provide a local directory and/or target to output the generated files to"),
182 << device_cred_gen_.lastStdErr();
197 const std::string base_path =
"my_device_cred";
198 const std::string private_key_file =
"my_device_private_key.pem";
199 const std::string cert_file =
"my_device_cert.pem";
202 config.import.base_path = base_path;
206 auto test_conf_file = tmp_dir_ /
"conf.toml";
207 boost::filesystem::ofstream conf_file(test_conf_file);
208 config.writeToStream(conf_file);
214 args.fleetCA = test_args_.fleet_ca_cert;
215 args.fleetCAKey = test_args_.fleet_ca_private_key;
216 args.localDir = test_args_.test_dir;
217 args.configFile = test_conf_file.string();
219 device_cred_gen_.run(args);
221 ASSERT_EQ(device_cred_gen_.lastExitCode(), 0) << device_cred_gen_.lastStdErr();
223 ASSERT_TRUE(boost::filesystem::exists(device_cred_path.privateKeyFileFullPath))
224 <<
"Private key file is missing: " << device_cred_path.privateKeyFileFullPath;
225 ASSERT_TRUE(boost::filesystem::exists(device_cred_path.certFileFullPath))
226 <<
"Certificate file is missing: " << device_cred_path.certFileFullPath;
230 args.directoryPrefix =
"whatever-dir";
232 device_cred_gen_.run(args);
233 EXPECT_EQ(device_cred_gen_.lastExitCode(), 1) << device_cred_gen_.lastStdErr();
234 EXPECT_EQ(device_cred_gen_.lastStdErr(),
235 "Directory (--directory) and config (--config) options cannot be used together\n")
236 << device_cred_gen_.lastStdErr();
254 const std::string validity_days =
"100";
255 auto expires_after_sec = (std::stoul(validity_days) * 24 * 3600) + 1;
256 std::unordered_map<int, std::string> subject_items = {
257 {NID_countryName,
"UA"},
258 {NID_stateOrProvinceName,
"Lviv"},
259 {NID_organizationName,
"ATS"},
260 {NID_commonName,
"ats.io"},
262 const std::string rsa_bits =
"1024";
266 args.fleetCA = test_args_.fleet_ca_cert;
267 args.fleetCAKey = test_args_.fleet_ca_private_key;
268 args.localDir = test_args_.test_dir;
270 args.validityDays = validity_days;
271 args.countryCode = subject_items[NID_countryName];
272 args.state = subject_items[NID_stateOrProvinceName];
273 args.organization = subject_items[NID_organizationName];
274 args.commonName = subject_items[NID_commonName];
275 args.rsaBits = rsa_bits;
277 device_cred_gen_.run(args);
278 ASSERT_EQ(device_cred_gen_.lastExitCode(), 0) << device_cred_gen_.lastStdErr();
282 ASSERT_TRUE(boost::filesystem::exists(device_cred_path.privateKeyFileFullPath))
283 << device_cred_path.privateKeyFileFullPath;
284 ASSERT_TRUE(boost::filesystem::exists(device_cred_path.certFileFullPath)) << device_cred_path.certFileFullPath;
287 Cert cert(device_cred_path.certFileFullPath.string());
288 for (
auto subject_item : subject_items) {
289 ASSERT_EQ(cert.getSubjectItemValue(subject_item.first), subject_item.second);
292 Process openssl(
"/usr/bin/openssl");
294 const std::string expected_key_str = str(boost::format(
"Private-Key: (%1% bit") % rsa_bits);
295 openssl.run({
"rsa",
"-in", device_cred_path.privateKeyFileFullPath.string(),
"-text",
"-noout"});
296 ASSERT_EQ(openssl.lastExitCode(), 0) << openssl.lastStdErr();
297 ASSERT_NE(openssl.lastStdOut().find(expected_key_str), std::string::npos);
300 openssl.run({
"x509",
"-in", device_cred_path.certFileFullPath.string(),
"-checkend",
301 std::to_string(expires_after_sec - 1024)});
303 ASSERT_EQ(openssl.lastExitCode(), 0) << openssl.lastStdOut();
304 ASSERT_NE(openssl.lastStdOut().find(
"Certificate will not expire"), std::string::npos);
307 {
"x509",
"-in", device_cred_path.certFileFullPath.string(),
"-checkend", std::to_string(expires_after_sec)});
308 ASSERT_EQ(openssl.lastExitCode(), 1) << openssl.lastStdOut();
309 ASSERT_NE(openssl.lastStdOut().find(
"Certificate will expire"), std::string::npos);
312 openssl.run({
"verify",
"-verbose",
"-CAfile", test_args_.fleet_ca_cert, device_cred_path.certFileFullPath.string()});
313 ASSERT_EQ(openssl.lastExitCode(), 0) << openssl.lastStdErr();
314 ASSERT_EQ(openssl.lastStdOut(), str(boost::format(
"%1%: OK\n") % device_cred_path.certFileFullPath.string()));
318 int main(
int argc,
char** argv) {
319 ::testing::InitGoogleTest(&argc, argv);
322 std::cerr <<
"A path to the cert_provider is not specified." << std::endl;
326 CERT_PROVIDER_PATH = argv[1];
327 std::cout <<
"Path to the cert_provider executable: " << CERT_PROVIDER_PATH << std::endl;
329 int test_run_res = RUN_ALL_TESTS();
Configuration object for an aktualizr instance running on a Primary ECU.
The BasedPath class Can represent an absolute or relative path, only readable through the BasePath::g...