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