Aktualizr
C++ SOTA Client
ostreemanager_test.cc
1 #include <gtest/gtest.h>
2 
3 #include <fstream>
4 #include <iostream>
5 #include <memory>
6 #include <string>
7 
8 #include <boost/algorithm/hex.hpp>
9 #include <boost/filesystem.hpp>
10 
11 #include "libaktualizr/config.h"
12 #include "package_manager/ostreemanager.h"
13 #include "storage/invstorage.h"
14 #include "utilities/utils.h"
15 
16 boost::filesystem::path test_sysroot;
17 
18 /* Reject bad OSTree server URIs. */
19 TEST(OstreeManager, PullBadUriNoCreds) {
20  TemporaryDirectory temp_dir;
21  Config config;
22  config.pacman.ostree_server = "bad-url";
23  config.pacman.type = PACKAGE_MANAGER_OSTREE;
24  config.pacman.sysroot = test_sysroot;
25  config.storage.path = temp_dir.Path();
26 
27  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
28  KeyManager keys(storage, config.keymanagerConfig());
29  keys.loadKeys();
30  Json::Value target_json_test;
31  target_json_test["hashes"]["sha256"] = "some_hash";
32  target_json_test["length"] = 0;
33  Uptane::Target target_test("test.deb", target_json_test);
35  OstreeManager::pull(config.pacman.sysroot, config.pacman.ostree_server, keys, target_test);
36 
37  EXPECT_EQ(result.result_code.num_code, data::ResultCode::Numeric::kInstallFailed);
38  EXPECT_EQ(result.description, "Failed to parse uri: bad-url");
39 }
40 
41 /* Reject bad OSTree server URIs. */
42 TEST(OstreeManager, PullBadUriWithCreds) {
43  TemporaryDirectory temp_dir;
44  Config config;
45  config.pacman.ostree_server = "bad-url";
46  config.pacman.type = PACKAGE_MANAGER_OSTREE;
47  config.pacman.sysroot = test_sysroot;
48  config.storage.path = temp_dir.Path();
49 
50  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
51  std::string ca = Utils::readFile("tests/test_data/prov/root.crt");
52  std::string pkey = Utils::readFile("tests/test_data/prov/pkey.pem");
53  std::string cert = Utils::readFile("tests/test_data/prov/client.pem");
54  storage->storeTlsCa(ca);
55  storage->storeTlsPkey(pkey);
56  storage->storeTlsCert(cert);
57  KeyManager keys(storage, config.keymanagerConfig());
58  keys.loadKeys();
59  Json::Value target_json_test;
60  target_json_test["hashes"]["sha256"] = "some_hash";
61  target_json_test["length"] = 0;
62  Uptane::Target target_test("test.deb", target_json_test);
64  OstreeManager::pull(config.pacman.sysroot, config.pacman.ostree_server, keys, target_test);
65 
66  EXPECT_EQ(result.result_code.num_code, data::ResultCode::Numeric::kInstallFailed);
67  EXPECT_EQ(result.description, "Failed to parse uri: bad-url");
68 }
69 
70 /* Reject bad OSTree server URIs. */
71 TEST(OstreeManager, InstallBadUri) {
72  Json::Value target_json;
73  target_json["hashes"]["sha256"] = "hash";
74  target_json["length"] = 0;
75  Uptane::Target target("branch-name-hash", target_json);
76  TemporaryDirectory temp_dir;
77  Config config;
78  config.pacman.type = PACKAGE_MANAGER_OSTREE;
79  config.pacman.sysroot = test_sysroot;
80  config.storage.path = temp_dir.Path();
81 
82  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
83  OstreeManager ostree(config.pacman, config.bootloader, storage, nullptr);
84  data::InstallationResult result = ostree.install(target);
85  EXPECT_EQ(result.result_code.num_code, data::ResultCode::Numeric::kInstallFailed);
86  EXPECT_EQ(result.description, "Refspec 'hash' not found");
87 }
88 
89 /* Abort if the OSTree sysroot is invalid. */
90 TEST(OstreeManager, BadSysroot) {
91  TemporaryDirectory temp_dir;
92  Config config;
93  config.pacman.type = PACKAGE_MANAGER_OSTREE;
94  config.pacman.sysroot = "sysroot-that-is-missing";
95  config.storage.path = temp_dir.Path();
96  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
97  EXPECT_THROW(OstreeManager ostree(config.pacman, config.bootloader, storage, nullptr), std::runtime_error);
98 }
99 
100 /* Parse a provided list of installed packages. */
101 TEST(OstreeManager, ParseInstalledPackages) {
102  TemporaryDirectory temp_dir;
103  boost::filesystem::path packages_file = temp_dir / "package.manifest";
104 
105  std::string content;
106  {
107  content += "vim 1.0\n";
108  content += "emacs 2.0\n";
109  content += "bash 1.1\n";
110  }
111  Utils::writeFile(packages_file, content);
112 
113  Config config;
114  config.pacman.type = PACKAGE_MANAGER_OSTREE;
115  config.pacman.sysroot = test_sysroot;
116  config.pacman.packages_file = packages_file;
117  config.storage.path = temp_dir.Path();
118 
119  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
120  OstreeManager ostree(config.pacman, config.bootloader, storage, nullptr);
121  Json::Value packages = ostree.getInstalledPackages();
122  EXPECT_EQ(packages[0]["name"].asString(), "vim");
123  EXPECT_EQ(packages[0]["version"].asString(), "1.0");
124  EXPECT_EQ(packages[1]["name"].asString(), "emacs");
125  EXPECT_EQ(packages[1]["version"].asString(), "2.0");
126  EXPECT_EQ(packages[2]["name"].asString(), "bash");
127  EXPECT_EQ(packages[2]["version"].asString(), "1.1");
128 }
129 
130 /* Communicate with a remote OSTree server without credentials. */
131 TEST(OstreeManager, AddRemoteNoCreds) {
132  TemporaryDirectory temp_dir;
133  Config config;
134  config.pacman.type = PACKAGE_MANAGER_OSTREE;
135  config.pacman.sysroot = test_sysroot;
136  config.storage.path = temp_dir.Path();
137 
138  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
139  KeyManager keys(storage, config.keymanagerConfig());
140  keys.loadKeys();
141 
142  OstreeRepo *repo = nullptr;
143  GError *error = nullptr;
144  std::shared_ptr<OstreeSysroot> sysroot = OstreeManager::LoadSysroot(config.pacman.sysroot);
145  EXPECT_TRUE(ostree_sysroot_get_repo(sysroot.get(), &repo, nullptr, &error));
146  EXPECT_TRUE(OstreeManager::addRemote(repo, config.pacman.ostree_server, keys));
147 
148  g_autofree char *url = nullptr;
149  EXPECT_TRUE(ostree_repo_get_remote_option(repo, remote, "url", nullptr, &url, &error));
150  EXPECT_EQ(url, config.pacman.ostree_server);
151 
152  gboolean out_gpg_verify;
153  EXPECT_TRUE(ostree_repo_get_remote_boolean_option(repo, remote, "gpg-verify", FALSE, &out_gpg_verify, &error));
154 
155  g_autofree char *ostree_cert = nullptr;
156  EXPECT_TRUE(ostree_repo_get_remote_option(repo, remote, "tls-client-cert-path", nullptr, &ostree_cert, &error));
157  EXPECT_EQ(ostree_cert, nullptr);
158 
159  g_autofree char *ostree_key = nullptr;
160  EXPECT_TRUE(ostree_repo_get_remote_option(repo, remote, "tls-client-key-path", nullptr, &ostree_key, &error));
161  EXPECT_EQ(ostree_key, nullptr);
162 
163  g_autofree char *ostree_ca = nullptr;
164  EXPECT_TRUE(ostree_repo_get_remote_option(repo, remote, "tls-ca-path", nullptr, &ostree_ca, &error));
165  EXPECT_EQ(ostree_ca, nullptr);
166 
167  g_object_unref(repo);
168 }
169 
170 /* Communicate with a remote OSTree server with credentials. */
171 TEST(OstreeManager, AddRemoteWithCreds) {
172  TemporaryDirectory temp_dir;
173  Config config;
174  config.pacman.type = PACKAGE_MANAGER_OSTREE;
175  config.pacman.sysroot = test_sysroot;
176  config.storage.path = temp_dir.Path();
177 
178  std::shared_ptr<INvStorage> storage = INvStorage::newStorage(config.storage);
179  std::string ca = Utils::readFile("tests/test_data/prov/root.crt");
180  std::string pkey = Utils::readFile("tests/test_data/prov/pkey.pem");
181  std::string cert = Utils::readFile("tests/test_data/prov/client.pem");
182  storage->storeTlsCa(ca);
183  storage->storeTlsPkey(pkey);
184  storage->storeTlsCert(cert);
185  KeyManager keys(storage, config.keymanagerConfig());
186  keys.loadKeys();
187 
188  OstreeRepo *repo = nullptr;
189  GError *error = nullptr;
190  std::shared_ptr<OstreeSysroot> sysroot = OstreeManager::LoadSysroot(config.pacman.sysroot);
191  EXPECT_TRUE(ostree_sysroot_get_repo(sysroot.get(), &repo, nullptr, &error));
192  EXPECT_TRUE(OstreeManager::addRemote(repo, config.pacman.ostree_server, keys));
193 
194  g_autofree char *url = nullptr;
195  EXPECT_TRUE(ostree_repo_get_remote_option(repo, remote, "url", nullptr, &url, &error));
196  EXPECT_EQ(url, config.pacman.ostree_server);
197 
198  gboolean out_gpg_verify;
199  EXPECT_TRUE(ostree_repo_get_remote_boolean_option(repo, remote, "gpg-verify", FALSE, &out_gpg_verify, &error));
200 
201  g_autofree char *ostree_cert = nullptr;
202  EXPECT_TRUE(ostree_repo_get_remote_option(repo, remote, "tls-client-cert-path", nullptr, &ostree_cert, &error));
203  EXPECT_EQ(ostree_cert, keys.getCertFile());
204 
205  g_autofree char *ostree_key = nullptr;
206  EXPECT_TRUE(ostree_repo_get_remote_option(repo, remote, "tls-client-key-path", nullptr, &ostree_key, &error));
207  EXPECT_EQ(ostree_key, keys.getPkeyFile());
208 
209  g_autofree char *ostree_ca = nullptr;
210  EXPECT_TRUE(ostree_repo_get_remote_option(repo, remote, "tls-ca-path", nullptr, &ostree_ca, &error));
211  EXPECT_EQ(ostree_ca, keys.getCaFile());
212 
213  g_object_unref(repo);
214 }
215 
216 #ifndef __NO_MAIN__
217 int main(int argc, char **argv) {
218  ::testing::InitGoogleTest(&argc, argv);
219 
220  if (argc != 2) {
221  std::cerr << "Error: " << argv[0] << " requires the path to an OSTree sysroot as an input argument.\n";
222  return EXIT_FAILURE;
223  }
224 
225  TemporaryDirectory temp_sysroot;
226  test_sysroot = temp_sysroot / "sysroot";
227  // uses cp, as boost doesn't like to copy bad symlinks
228  int r = system((std::string("cp -r ") + argv[1] + std::string(" ") + test_sysroot.string()).c_str());
229  if (r != 0) {
230  return -1;
231  }
232 
233  return RUN_ALL_TESTS();
234 }
235 #endif
KeyManager
Definition: keymanager.h:13
data::InstallationResult
Definition: types.h:277
Config
Configuration object for an aktualizr instance running on a Primary ECU.
Definition: config.h:208
OstreeManager
Definition: ostreemanager.h:41
TemporaryDirectory
Definition: utils.h:82
result
Results of libaktualizr API calls.
Definition: results.h:12
Uptane::Target
Definition: types.h:379
data::ResultCode::Numeric::kInstallFailed
@ kInstallFailed
Package installation failed.