Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2021 CESNET, https://photonics.cesnet.cz/ |
| 3 | * |
| 4 | * Written by Václav Kubernát <kubernat@cesnet.cz> |
| 5 | * |
| 6 | */ |
| 7 | |
| 8 | #include <fmt/core.h> |
| 9 | #include <fstream> |
Tomáš Pecka | 72f540e | 2024-07-08 13:45:22 +0200 | [diff] [blame^] | 10 | #include <libyang-cpp/Time.hpp> |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 11 | #include <pwd.h> |
| 12 | #include <shadow.h> |
| 13 | #include <spdlog/spdlog.h> |
| 14 | #include <sstream> |
| 15 | #include "Authentication.h" |
| 16 | #include "system_vars.h" |
| 17 | #include "utils/exec.h" |
| 18 | #include "utils/io.h" |
| 19 | #include "utils/libyang.h" |
| 20 | #include "utils/sysrepo.h" |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 21 | |
| 22 | using namespace std::string_literals; |
| 23 | namespace { |
| 24 | const auto czechlight_system_module = "czechlight-system"s; |
| 25 | const auto authentication_container = "/" + czechlight_system_module + ":authentication"; |
| 26 | const auto change_password_action = "/" + czechlight_system_module + ":authentication/users/change-password"; |
| 27 | const auto add_key_action = "/" + czechlight_system_module + ":authentication/users/add-authorized-key"; |
| 28 | const auto remove_key_action = "/" + czechlight_system_module + ":authentication/users/authorized-keys/remove"; |
| 29 | } |
| 30 | |
| 31 | namespace velia::system { |
| 32 | namespace { |
| 33 | |
| 34 | void writeKeys(const std::string& filename, const std::vector<std::string>& keys) |
| 35 | { |
| 36 | std::ostringstream ss; |
| 37 | |
| 38 | for (const auto& key : keys) { |
| 39 | ss << key << "\n"; |
| 40 | } |
Václav Kubernát | b6adbde | 2021-10-11 22:06:06 +0200 | [diff] [blame] | 41 | |
| 42 | std::filesystem::create_directories(std::filesystem::path(filename).parent_path()); |
| 43 | |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 44 | utils::safeWriteFile(filename, ss.str()); |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | namespace impl { |
Tomáš Pecka | d9e741f | 2021-02-10 15:51:17 +0100 | [diff] [blame] | 49 | void changePassword(const std::string& name, const std::string& password, const std::string& etc_shadow) |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 50 | { |
| 51 | utils::execAndWait(spdlog::get("system"), CHPASSWD_EXECUTABLE, {}, name + ":" + password); |
Tomáš Pecka | d9e741f | 2021-02-10 15:51:17 +0100 | [diff] [blame] | 52 | auto shadow = velia::utils::readFileToString(etc_shadow); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 53 | utils::safeWriteFile(BACKUP_ETC_SHADOW_FILE, shadow); |
| 54 | } |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 55 | |
| 56 | auto file_open(const char* filename, const char* mode) |
| 57 | { |
Jan Kundrát | 343011f | 2023-11-13 17:40:08 +0100 | [diff] [blame] | 58 | auto res = std::unique_ptr<std::FILE, decltype([](auto fp) { std::fclose(fp); })>(std::fopen(filename, mode)); |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 59 | if (!res.get()) { |
| 60 | throw std::system_error{errno, std::system_category(), "fopen("s + filename + ") failed"}; |
| 61 | } |
| 62 | return res; |
| 63 | } |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | std::string Authentication::homeDirectory(const std::string& username) |
| 67 | { |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 68 | auto passwdFile = impl::file_open(m_etc_passwd.c_str(), "r"); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 69 | passwd entryBuf; |
| 70 | size_t bufLen = 10; |
| 71 | auto buffer = std::make_unique<char[]>(bufLen); |
| 72 | passwd* entry; |
| 73 | |
| 74 | while (true) { |
Václav Kubernát | 515cef0 | 2021-03-25 05:48:57 +0100 | [diff] [blame] | 75 | auto pos = ftell(passwdFile.get()); |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 76 | auto ret = fgetpwent_r(passwdFile.get(), &entryBuf, buffer.get(), bufLen, &entry); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 77 | if (ret == ERANGE) { |
| 78 | bufLen += 100; |
| 79 | buffer = std::make_unique<char[]>(bufLen); |
Václav Kubernát | 515cef0 | 2021-03-25 05:48:57 +0100 | [diff] [blame] | 80 | fseek(passwdFile.get(), pos, SEEK_SET); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 81 | continue; |
| 82 | } |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 83 | |
| 84 | if (ret == ENOENT) { |
| 85 | break; |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 86 | } |
| 87 | |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 88 | if (ret != 0) { |
| 89 | throw std::system_error{ret, std::system_category(), "fgetpwent_r() failed"}; |
| 90 | } |
| 91 | |
| 92 | assert(entry); |
| 93 | |
| 94 | if (username != entry->pw_name) { |
| 95 | continue; |
| 96 | } |
| 97 | |
| 98 | return entry->pw_dir; |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 99 | } |
| 100 | |
| 101 | throw std::runtime_error("User " + username + " doesn't exist"); |
| 102 | } |
| 103 | |
Václav Kubernát | 8ea630e | 2021-02-18 16:55:25 +0100 | [diff] [blame] | 104 | std::map<std::string, std::optional<std::string>> Authentication::lastPasswordChanges() |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 105 | { |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 106 | auto shadowFile = impl::file_open(m_etc_shadow.c_str(), "r"); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 107 | spwd entryBuf; |
| 108 | size_t bufLen = 10; |
| 109 | auto buffer = std::make_unique<char[]>(bufLen); |
| 110 | spwd* entry; |
| 111 | |
Václav Kubernát | 8ea630e | 2021-02-18 16:55:25 +0100 | [diff] [blame] | 112 | std::map<std::string, std::optional<std::string>> res; |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 113 | while (true) { |
Václav Kubernát | 515cef0 | 2021-03-25 05:48:57 +0100 | [diff] [blame] | 114 | auto pos = ftell(shadowFile.get()); |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 115 | auto ret = fgetspent_r(shadowFile.get(), &entryBuf, buffer.get(), bufLen, &entry); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 116 | if (ret == ERANGE) { |
| 117 | bufLen += 100; |
| 118 | buffer = std::make_unique<char[]>(bufLen); |
Václav Kubernát | 515cef0 | 2021-03-25 05:48:57 +0100 | [diff] [blame] | 119 | fseek(shadowFile.get(), pos, SEEK_SET); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 120 | continue; |
| 121 | } |
| 122 | |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 123 | if (ret == ENOENT) { |
| 124 | break; |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 125 | } |
| 126 | |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 127 | if (ret != 0) { |
| 128 | throw std::system_error{ret, std::system_category(), "fgetspent_r() failed"}; |
| 129 | } |
| 130 | |
| 131 | assert(entry); |
| 132 | |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 133 | using namespace std::chrono_literals; |
Tomáš Pecka | 72f540e | 2024-07-08 13:45:22 +0200 | [diff] [blame^] | 134 | using TimeType = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>; |
| 135 | res.emplace(entry->sp_namp, libyang::yangTimeFormat(TimeType(24h * entry->sp_lstchg), libyang::TimezoneInterpretation::Local)); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 136 | } |
| 137 | |
Václav Kubernát | 8ea630e | 2021-02-18 16:55:25 +0100 | [diff] [blame] | 138 | return res; |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 139 | } |
| 140 | |
| 141 | std::string Authentication::authorizedKeysPath(const std::string& username) |
| 142 | { |
| 143 | using namespace fmt::literals; |
Tomáš Pecka | af4abff | 2023-01-18 12:23:53 +0100 | [diff] [blame] | 144 | return fmt::format(fmt::runtime(m_authorized_keys_format), "USER"_a=username, "HOME"_a=homeDirectory(username)); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | std::vector<std::string> Authentication::listKeys(const std::string& username) |
| 148 | { |
| 149 | std::vector<std::string> res; |
| 150 | std::ifstream ifs(authorizedKeysPath(username)); |
| 151 | if (!ifs.is_open()) { |
| 152 | return res; |
| 153 | } |
| 154 | std::string line; |
| 155 | while (std::getline(ifs, line)) { |
| 156 | if (line.find_first_not_of(" \r\t") == std::string::npos) { |
| 157 | continue; |
| 158 | } |
| 159 | |
| 160 | res.emplace_back(line); |
| 161 | } |
| 162 | |
| 163 | return res; |
| 164 | } |
| 165 | |
| 166 | std::vector<User> Authentication::listUsers() |
| 167 | { |
| 168 | std::vector<User> res; |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 169 | auto passwdFile = impl::file_open(m_etc_passwd.c_str(), "r"); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 170 | passwd entryBuf; |
| 171 | size_t bufLen = 10; |
| 172 | auto buffer = std::make_unique<char[]>(bufLen); |
| 173 | passwd* entry; |
| 174 | |
Václav Kubernát | 8ea630e | 2021-02-18 16:55:25 +0100 | [diff] [blame] | 175 | auto pwChanges = lastPasswordChanges(); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 176 | while (true) { |
Václav Kubernát | 515cef0 | 2021-03-25 05:48:57 +0100 | [diff] [blame] | 177 | auto pos = ftell(passwdFile.get()); |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 178 | auto ret = fgetpwent_r(passwdFile.get(), &entryBuf, buffer.get(), bufLen, &entry); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 179 | if (ret == ERANGE) { |
| 180 | bufLen += 100; |
| 181 | buffer = std::make_unique<char[]>(bufLen); |
Václav Kubernát | 515cef0 | 2021-03-25 05:48:57 +0100 | [diff] [blame] | 182 | fseek(passwdFile.get(), pos, SEEK_SET); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 183 | continue; |
| 184 | } |
| 185 | |
| 186 | if (ret == ENOENT) { |
| 187 | break; |
| 188 | } |
Jan Kundrát | b25ef24 | 2021-02-18 14:56:54 +0100 | [diff] [blame] | 189 | |
| 190 | if (ret != 0) { |
| 191 | throw std::system_error{ret, std::system_category(), "fgetpwent_r() failed"}; |
| 192 | } |
| 193 | |
| 194 | assert(entry); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 195 | User user; |
| 196 | user.name = entry->pw_name; |
| 197 | user.authorizedKeys = listKeys(user.name); |
Václav Kubernát | 8ea630e | 2021-02-18 16:55:25 +0100 | [diff] [blame] | 198 | if (auto it = pwChanges.find(user.name); it != pwChanges.end()) { |
| 199 | user.lastPasswordChange = it->second; |
| 200 | } |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 201 | res.emplace_back(user); |
| 202 | } |
| 203 | |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 204 | return res; |
| 205 | } |
| 206 | |
| 207 | void Authentication::addKey(const std::string& username, const std::string& key) |
| 208 | { |
| 209 | try { |
| 210 | utils::execAndWait(spdlog::get("system"), SSH_KEYGEN_EXECUTABLE, {"-l", "-f", "-"}, key, {utils::ExecOptions::DropRoot}); |
| 211 | } catch (std::runtime_error& ex) { |
| 212 | using namespace fmt::literals; |
| 213 | throw AuthException(fmt::format("Key is not a valid SSH public key: {stderr}\n{key}", "stderr"_a=ex.what(), "key"_a=key)); |
| 214 | } |
| 215 | auto currentKeys = listKeys(username); |
| 216 | currentKeys.emplace_back(key); |
| 217 | writeKeys(authorizedKeysPath(username), currentKeys); |
| 218 | } |
| 219 | |
| 220 | void Authentication::removeKey(const std::string& username, const int index) |
| 221 | { |
| 222 | auto currentKeys = listKeys(username); |
| 223 | if (currentKeys.size() == 1) { |
| 224 | // FIXME: maybe add an option to bypass this check? |
| 225 | throw AuthException("Can't remove last key."); |
| 226 | } |
| 227 | currentKeys.erase(currentKeys.begin() + index); |
| 228 | writeKeys(authorizedKeysPath(username), currentKeys); |
| 229 | } |
| 230 | } |
| 231 | |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 232 | void usersToTree(libyang::Context ctx, const std::vector<velia::system::User> users, std::optional<libyang::DataNode>& out) |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 233 | { |
Jan Kundrát | b3e9998 | 2022-03-18 17:38:20 +0100 | [diff] [blame] | 234 | out = ctx.newPath(authentication_container); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 235 | for (const auto& user : users) { |
Jan Kundrát | b3e9998 | 2022-03-18 17:38:20 +0100 | [diff] [blame] | 236 | auto userNode = out->newPath("users[name='" + user.name + "']", std::nullopt); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 237 | |
| 238 | decltype(user.authorizedKeys)::size_type entries = 0; |
| 239 | for (const auto& authorizedKey : user.authorizedKeys) { |
Jan Kundrát | b3e9998 | 2022-03-18 17:38:20 +0100 | [diff] [blame] | 240 | auto entry = userNode->newPath("authorized-keys[index='" + std::to_string(entries) + "']"); |
| 241 | entry->newPath("public-key", authorizedKey); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 242 | entries++; |
| 243 | } |
| 244 | |
| 245 | if (user.lastPasswordChange) { |
Jan Kundrát | b3e9998 | 2022-03-18 17:38:20 +0100 | [diff] [blame] | 246 | userNode->newPath("password-last-change", user.lastPasswordChange); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 247 | } |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | velia::system::Authentication::Authentication( |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 252 | sysrepo::Session srSess, |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 253 | const std::string& etc_passwd, |
| 254 | const std::string& etc_shadow, |
| 255 | const std::string& authorized_keys_format, |
| 256 | ChangePassword changePassword |
| 257 | ) |
| 258 | : m_log(spdlog::get("system")) |
| 259 | , m_etc_passwd(etc_passwd) |
| 260 | , m_etc_shadow(etc_shadow) |
| 261 | , m_authorized_keys_format(authorized_keys_format) |
| 262 | , m_session(srSess) |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 263 | , m_sub() |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 264 | { |
| 265 | m_log->debug("Initializing authentication"); |
| 266 | m_log->debug("Using {} as passwd file", m_etc_passwd); |
| 267 | m_log->debug("Using {} as shadow file", m_etc_shadow); |
| 268 | m_log->debug("Using {} authorized_keys format", m_authorized_keys_format); |
Jan Kundrát | 7a30cf4 | 2022-07-12 22:24:09 +0200 | [diff] [blame] | 269 | utils::ensureModuleImplemented(srSess, "czechlight-system", "2022-07-08"); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 270 | |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 271 | sysrepo::OperGetCb listUsersCb = [this] (auto session, auto, auto, auto, auto, auto, auto& out) { |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 272 | m_log->debug("Listing users"); |
| 273 | |
| 274 | auto users = listUsers(); |
| 275 | m_log->trace("got {} users", users.size()); |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 276 | usersToTree(session.getContext(), users, out); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 277 | |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 278 | return sysrepo::ErrorCode::Ok; |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 279 | }; |
| 280 | |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 281 | sysrepo::RpcActionCb changePasswordCb = [this, changePassword] (auto, auto, auto, auto input, auto, auto, auto output) { |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 282 | |
Jan Kundrát | b3e9998 | 2022-03-18 17:38:20 +0100 | [diff] [blame] | 283 | auto userNode = utils::getUniqueSubtree(input, authentication_container + "/users").value(); |
Tomáš Pecka | fd90efb | 2021-10-07 10:40:44 +0200 | [diff] [blame] | 284 | auto name = utils::getValueAsString(utils::getUniqueSubtree(userNode, "name").value()); |
| 285 | auto password = utils::getValueAsString(utils::getUniqueSubtree(userNode, "change-password/password-cleartext").value()); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 286 | m_log->debug("Changing password for {}", name); |
| 287 | try { |
Tomáš Pecka | d9e741f | 2021-02-10 15:51:17 +0100 | [diff] [blame] | 288 | changePassword(name, password, m_etc_shadow); |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 289 | output.newPath("result", "success", libyang::CreationOptions::Output); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 290 | m_log->info("Changed password for {}", name); |
| 291 | } catch (std::runtime_error& ex) { |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 292 | output.newPath("result", "failure", libyang::CreationOptions::Output); |
| 293 | output.newPath("message", ex.what(), libyang::CreationOptions::Output); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 294 | m_log->info("Failed to change password for {}: {}", name, ex.what()); |
| 295 | } |
| 296 | |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 297 | return sysrepo::ErrorCode::Ok; |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 298 | }; |
| 299 | |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 300 | sysrepo::RpcActionCb addKeyCb = [this] (auto, auto, auto, auto input, auto, auto, auto output) { |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 301 | |
Jan Kundrát | b3e9998 | 2022-03-18 17:38:20 +0100 | [diff] [blame] | 302 | auto userNode = utils::getUniqueSubtree(input, authentication_container + "/users").value(); |
Tomáš Pecka | fd90efb | 2021-10-07 10:40:44 +0200 | [diff] [blame] | 303 | auto name = utils::getValueAsString(utils::getUniqueSubtree(userNode, "name").value()); |
| 304 | auto key = utils::getValueAsString(utils::getUniqueSubtree(userNode, "add-authorized-key/key").value()); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 305 | m_log->debug("Adding key for {}", name); |
| 306 | try { |
| 307 | addKey(name, key); |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 308 | output.newPath("result", "success", libyang::CreationOptions::Output); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 309 | m_log->info("Added a key for {}", name); |
| 310 | } catch (AuthException& ex) { |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 311 | output.newPath("result", "failure", libyang::CreationOptions::Output); |
| 312 | output.newPath("message", ex.what(), libyang::CreationOptions::Output); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 313 | m_log->warn("Failed to add a key for {}: {}", name, ex.what()); |
| 314 | } |
| 315 | |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 316 | return sysrepo::ErrorCode::Ok; |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 317 | }; |
| 318 | |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 319 | sysrepo::RpcActionCb removeKeyCb = [this] (auto, auto, auto, auto input, auto, auto, auto output) { |
Jan Kundrát | b3e9998 | 2022-03-18 17:38:20 +0100 | [diff] [blame] | 320 | auto userNode = utils::getUniqueSubtree(input, authentication_container + "/users").value(); |
Tomáš Pecka | fd90efb | 2021-10-07 10:40:44 +0200 | [diff] [blame] | 321 | auto name = utils::getValueAsString(utils::getUniqueSubtree(userNode, "name").value()); |
| 322 | auto key = std::stol(utils::getValueAsString(utils::getUniqueSubtree(userNode, "authorized-keys/index").value())); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 323 | m_log->debug("Removing key for {}", name); |
| 324 | try { |
| 325 | removeKey(name, key); |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 326 | output.newPath("result", "success", libyang::CreationOptions::Output); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 327 | m_log->info("Removed key for {}", name); |
| 328 | } catch (AuthException& ex) { |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 329 | output.newPath("result", "failure", libyang::CreationOptions::Output); |
| 330 | output.newPath("message", ex.what(), libyang::CreationOptions::Output); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 331 | m_log->warn("Failed to remove a key for {}: {}", name, ex.what()); |
| 332 | } |
| 333 | |
Václav Kubernát | 7efd6d5 | 2021-11-09 01:31:11 +0100 | [diff] [blame] | 334 | return sysrepo::ErrorCode::Ok; |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 335 | }; |
| 336 | |
Jan Kundrát | b3e9998 | 2022-03-18 17:38:20 +0100 | [diff] [blame] | 337 | m_sub = m_session.onOperGet(czechlight_system_module, listUsersCb, authentication_container); |
| 338 | m_sub->onRPCAction(change_password_action, changePasswordCb); |
| 339 | m_sub->onRPCAction(add_key_action, addKeyCb); |
| 340 | m_sub->onRPCAction(remove_key_action, removeKeyCb); |
Václav Kubernát | babbab9 | 2021-01-27 09:25:05 +0100 | [diff] [blame] | 341 | } |