diff --git a/.gitignore b/.gitignore index 7a56b55..30b284c 100755 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,4 @@ CMakeLists.txt.user* # Output files build/ +_tmp/ diff --git a/CMakeLists.txt b/CMakeLists.txt index ffe7e4d..a511b30 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ include(CTest) include(GNUInstallDirs) set(PROJECT_VERSION_MAJOR 2) -set(PROJECT_VERSION_MINOR 1) +set(PROJECT_VERSION_MINOR 2) set(PROJECT_VERSION_PATCH 0) set(RUBLON_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") @@ -17,6 +17,9 @@ set(CMAKE_POSITION_INDEPENDENT_CODE YES) add_compile_options(-Wall -Wextra -Wno-format-security) +# add_compile_options(-g -fsanitize=address,undefined,float-divide-by-zero,float-cast-overflow,null -fsanitize-address-use-after-scope -fno-sanitize-recover=all -fno-sanitize=alignment -fno-omit-frame-pointer) +# add_link_options(-g -fsanitize=address,undefined,float-divide-by-zero,float-cast-overflow,null -fsanitize-address-use-after-scope -fno-sanitize-recover=all -fno-sanitize=alignment -fno-omit-frame-pointer) + add_compile_definitions(RUBLON_VERSION_STRING="${RUBLON_VERSION_STRING}") option(ENABLE_TESTS "Enable tests" OFF) @@ -25,13 +28,16 @@ add_custom_target(INSTSCRIPTS_IDE SUORCES ${CMAKE_CURRENT_LIST_DIR}/service/help execute_process ( COMMAND bash -c "awk -F= '/^ID=/{print $2}' /etc/os-release |tr -d '\n' | tr -d '\"'" - OUTPUT_VARIABLE outOS + RESULT_VARIABLE outOS ) + +if ( ${outOS} MATCHES "ubuntu" OR ${outOS} MATCHES "debian" OR ${outOS} MATCHES "FREEBSD" ) install( FILES - ${CMAKE_CURRENT_LIST_DIR}/rsc/rublon.config.defaults + ${CMAKE_CURRENT_LIST_DIR}/rsc/rublon.config.defaults ${CMAKE_CURRENT_LIST_DIR}/service/01-rublon-ssh_pubkey.conf.default ${CMAKE_CURRENT_LIST_DIR}/service/01-rublon-ssh.conf.default + ${CMAKE_CURRENT_LIST_DIR}/service/inst_pubkey.sh DESTINATION share/rublon COMPONENT @@ -41,15 +47,20 @@ install( OWNER_WRITE GROUP_READ ) - -if (NOT ${outOS} MATCHES "ubuntu" OR NOT ${outOS} MATCHES "debian" OR NOT ${outOS} MATCHES "FREEBSD") +else () install( FILES - ${CMAKE_CURRENT_LIST_DIR}/service/login_rublon.mod - ${CMAKE_CURRENT_LIST_DIR}/service/login_rublon.pp - ${CMAKE_CURRENT_LIST_DIR}/service/login_rublon.te - ${CMAKE_CURRENT_LIST_DIR}/service/pam_service.txt - ${CMAKE_CURRENT_LIST_DIR}/service/rublon_veritas + ${CMAKE_CURRENT_LIST_DIR}/rsc/rublon.config.defaults + ${CMAKE_CURRENT_LIST_DIR}/service/01-rublon-ssh_pubkey.conf.default + ${CMAKE_CURRENT_LIST_DIR}/service/01-rublon-ssh.conf.default + ${CMAKE_CURRENT_LIST_DIR}/service/login_rublon.mod + ${CMAKE_CURRENT_LIST_DIR}/service/login_rublon.pp + ${CMAKE_CURRENT_LIST_DIR}/service/login_rublon.te + ${CMAKE_CURRENT_LIST_DIR}/service/pam_service.txt + ${CMAKE_CURRENT_LIST_DIR}/service/rublon_veritas + ${CMAKE_CURRENT_LIST_DIR}/service/inst_pubkey_rhel_9.sh + ${CMAKE_CURRENT_LIST_DIR}/service/inst_pubkey_rhel_8.sh + ${CMAKE_CURRENT_LIST_DIR}/service/inst_pubkey.sh DESTINATION share/rublon COMPONENT diff --git a/PAM/ssh/CMakeLists.txt b/PAM/ssh/CMakeLists.txt index 94cee9c..26dad44 100755 --- a/PAM/ssh/CMakeLists.txt +++ b/PAM/ssh/CMakeLists.txt @@ -79,6 +79,7 @@ set(LWS_UNIX_SOCK OFF) set(LWS_WITH_DIR OFF) set(LWS_WITH_FILE_OPS OFF) +set(LWS_FOR_GITOHASHI OFF) set(LWS_WITH_HTTP2 OFF) set(LWS_WITH_HTTP_BASIC_AUTH OFF) set(LWS_WITH_JPEG OFF) @@ -94,6 +95,9 @@ set(LWS_WITH_SECURE_STREAMS OFF) set(LWS_WITH_WOL OFF) set(LWS_WITH_UPNG OFF) set(LWS_WITH_UDP OFF) +set(LWS_WITH_HTTP_STREAM_COMPRESSION OFF) +set(LWS_WITH_HTTP_BROTLI OFF) +set(LWS_WITH_ZLIB OFF) set(RAPIDJSON_BUILD_DOC OFF CACHE BOOL "" FORCE) set(RAPIDJSON_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) @@ -114,10 +118,17 @@ FetchContent_Declare( FetchContent_MakeAvailable(libwebsockets) + +set(RAPIDJSON_BUILD_DOC OFF) +set(RAPIDJSON_BUILD_EXAMPLES OFF) +set(RAPIDJSON_BUILD_TESTS OFF) +set(RAPIDJSON_HAS_STDSTRING OFF) + FetchContent_Declare( RapidJSON - URL https://github.com/Tencent/rapidjson/archive/refs/tags/v1.1.0.zip - URL_HASH MD5=ceb1cf16e693a3170c173dc040a9d2bd + URL https://github.com/Tencent/rapidjson/archive/refs/tags/v1.1.0.zip + URL_HASH MD5=ceb1cf16e693a3170c173dc040a9d2bd + PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_LIST_DIR}/patches/rapidjson.patch ) if(NOT RapidJSON_POPULATED) diff --git a/PAM/ssh/include/rublon/authentication_step_interface.hpp b/PAM/ssh/include/rublon/authentication_step_interface.hpp index 2ae65b4..63f7ad3 100644 --- a/PAM/ssh/include/rublon/authentication_step_interface.hpp +++ b/PAM/ssh/include/rublon/authentication_step_interface.hpp @@ -29,6 +29,17 @@ class AuthenticationStep { auto & alloc = body.GetAllocator(); body.AddMember("accessToken", Value{token.data(), static_cast< unsigned >(token.length()), alloc}, alloc); } + + template < typename Hander_t > + tl::expected< AuthenticationStatus, Error > waitForCoreConfirmation(const CoreHandlerInterface< Hander_t > & eventListener) const { + auto event = eventListener.listen(); + if(event.status == transactionConfirmed ){ + log(LogLevel::Debug, " Transaction confirmed"); + return AuthenticationStatus{AuthenticationStatus::Action::Confirmed, std::string{event.accessToken.value().c_str()}}; + } + log(LogLevel::Debug, " Transaction denied"); + return AuthenticationStatus{AuthenticationStatus::Action::Denied}; + } }; } // namespace rublon diff --git a/PAM/ssh/include/rublon/check_application.hpp b/PAM/ssh/include/rublon/check_application.hpp index 648ee89..c038c75 100644 --- a/PAM/ssh/include/rublon/check_application.hpp +++ b/PAM/ssh/include/rublon/check_application.hpp @@ -59,7 +59,7 @@ class Status { std::ifstream ifs{_statusFilePath.data()}; if(!ifs.is_open()) { - /// TODO handle no file error + return; } rapidjson::IStreamWrapper isw{ifs}; @@ -67,7 +67,7 @@ class Status { } void updateAppVersion(std::string_view newVersion) { - RapidJSONPMRStackAlloc< 128 > stackAlloc; + RapidJSONPMRStackAlloc< 512 > stackAlloc; auto jsonPointer = JSONPointer{_appVersionKey.data(), &stackAlloc}; auto version = jsonPointer.Get(_data); if(not version || version->GetString() != newVersion) { @@ -77,7 +77,7 @@ class Status { } void updateSystemVersion(std::string_view system) { - RapidJSONPMRStackAlloc< 128 > stackAlloc; + RapidJSONPMRStackAlloc< 512 > stackAlloc; auto jsonPointer = JSONPointer{_paramSystemName.data(), &stackAlloc}; auto version = jsonPointer.Get(_data); if(not version || version->GetString() != system) { @@ -88,7 +88,7 @@ class Status { void updateSSHDConfig() { using namespace std::string_view_literals; - constexpr auto keys = make_array("authenticationmethods"sv, + constexpr auto keys = make_array("authenticationmethods"sv, "challengeresponseauthentication"sv, "kbdinteractiveauthentication"sv, "logingracetime"sv, diff --git a/PAM/ssh/include/rublon/configuration.hpp b/PAM/ssh/include/rublon/configuration.hpp index 6404f92..6e8ae4a 100644 --- a/PAM/ssh/include/rublon/configuration.hpp +++ b/PAM/ssh/include/rublon/configuration.hpp @@ -27,6 +27,7 @@ class Configuration { bool logging{}; bool autopushPrompt{}; FailMode failMode{}; + bool nonInteractiveMode{}; }; namespace { @@ -138,7 +139,7 @@ constexpr auto make_entry(const char * name, const char * defaultValue) { return Entry{name, defaultValue, Entry::make_read_function< member >()}; } -constexpr static inline std::array< Entry, 8 > configurationVariables = { // +constexpr static inline std::array< Entry, 9 > configurationVariables = { // make_entry< &Configuration::logging >("logging", "true"), make_entry< &Configuration::systemToken >("systemToken", nullptr), make_entry< &Configuration::secretKey >("secretKey", nullptr), @@ -146,7 +147,9 @@ constexpr static inline std::array< Entry, 8 > configurationVariables = { // make_entry< &Configuration::prompt >("prompt", "1"), make_entry< &Configuration::enablePasswdEmail >("enablePasswdEmail", "true"), make_entry< &Configuration::autopushPrompt >("autopushPrompt", "false"), - make_entry< &Configuration::failMode >("failMode", "deny")}; + make_entry< &Configuration::failMode >("failMode", "deny"), + make_entry< &Configuration::nonInteractiveMode >("nonInteractiveMode", "false") +}; class ConfigurationFactory { public: diff --git a/PAM/ssh/include/rublon/core_handler.hpp b/PAM/ssh/include/rublon/core_handler.hpp index e0a030b..0168318 100755 --- a/PAM/ssh/include/rublon/core_handler.hpp +++ b/PAM/ssh/include/rublon/core_handler.hpp @@ -1,5 +1,6 @@ #pragma once +#include "rublon/error.hpp" #include "rublon/static_string.hpp" #include #include @@ -57,11 +58,13 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { } bool hasException(const Document & coreResponse) const { + log(LogLevel::Trace, "Checking error status in core response"); using namespace std::string_view_literals; return coreResponse.HasMember("status") and coreResponse["status"].GetString() == "ERROR"sv; } bool isUnHealthy(const Document & coreResponse) const { + log(LogLevel::Trace, "Checking errors in core response"); return coreResponse.HasParseError(); } @@ -102,7 +105,7 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { tl::expected< Document, Error > resp{&alloc}; resp->Parse(response.body.c_str()); - log(LogLevel::Debug, "Begin, Core Response validation"); + log(LogLevel::Debug, "Starting Core Response validation"); if(isUnHealthy(*resp)) { log(LogLevel::Error, "Rublon Core responded with broken data"); @@ -122,11 +125,13 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { // additional check for mallformed responses (A invalid response, without any x-rublon-signature will stop at this check) return tl::unexpected{CoreHandlerError{CoreHandlerError::BadSigature}}; } - + + log(LogLevel::Debug, "Core Response validated OK"); return resp; } tl::unexpected< Error > handleCoreException(std::string_view exceptionString) const { + log(LogLevel::Debug, "TMP got core exception: %s", exceptionString.data() ); // can happen only dyring check application step if(auto error = RublonCheckApplicationException::fromString(exceptionString); error.has_value()) return tl::unexpected{Error{error.value()}}; @@ -138,9 +143,10 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { // verification error wrong passcode etc. if(auto error = WerificationError::fromString(exceptionString); error.has_value()) return tl::unexpected{Error{error.value()}}; - + + // CoreHandlerError::TransactionAccessTokenExpiredException + // other exceptions, just "throw" - // TODO Handle return tl::unexpected{Error{CoreHandlerError{CoreHandlerError::RublonCoreException}}}; } diff --git a/PAM/ssh/include/rublon/core_handler_interface.hpp b/PAM/ssh/include/rublon/core_handler_interface.hpp index a0974d4..b0ba392 100644 --- a/PAM/ssh/include/rublon/core_handler_interface.hpp +++ b/PAM/ssh/include/rublon/core_handler_interface.hpp @@ -16,7 +16,7 @@ class CoreHandlerInterface { } bool createWSConnection(std::string_view tid) const { - rublon::log(LogLevel::Debug, "%s", "CoreHandlerInterface::listen"); + rublon::log(LogLevel::Debug, "%s", "CoreHandlerInterface::createWSConnection"); return static_cast< const Impl * >(this)->createWSConnection(tid); } diff --git a/PAM/ssh/include/rublon/curl.hpp b/PAM/ssh/include/rublon/curl.hpp index 4129d76..162962c 100644 --- a/PAM/ssh/include/rublon/curl.hpp +++ b/PAM/ssh/include/rublon/curl.hpp @@ -62,7 +62,6 @@ class CURL { std::pmr::string response_data{&stackResource}; response_data.reserve(3000); - /// TODO this can be done on stack using pmr auto curl_headers = std::unique_ptr< curl_slist, void (*)(curl_slist *) >(nullptr, curl_slist_free_all); std::for_each(request.headers.begin(), request.headers.end(), [&](auto header) { log(LogLevel::Debug, "%s header: %s: %s", "CURL", header.first.c_str(), header.second.c_str()); diff --git a/PAM/ssh/include/rublon/error.hpp b/PAM/ssh/include/rublon/error.hpp index bbb5d3d..21af816 100755 --- a/PAM/ssh/include/rublon/error.hpp +++ b/PAM/ssh/include/rublon/error.hpp @@ -1,17 +1,14 @@ #pragma once +#include #include #include #include +#include namespace rublon { -template < typename... Types > -constexpr std::array< std::string_view, sizeof...(Types) > make_array(Types... names) { - return {std::forward< Types >(names)...}; -} - class ConfigurationError { public: enum class ErrorClass { // @@ -20,7 +17,7 @@ class ConfigurationError { BadInput, Empty }; - constexpr static auto errorClassPrettyName = make_array( // + constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "RequiredValueNotFound", "BadFailMode", "BadInput", @@ -43,7 +40,7 @@ class ConnectionError { HttpError, ClientError }; - constexpr static auto errorClassPrettyName = make_array( // + constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "Timeout", "Error", "Client Error"); @@ -72,7 +69,7 @@ class CoreHandlerError { TransactionAccessTokenExpiredException, // code: 11 TooManyRequestsException }; - constexpr static auto errorClassPrettyName = make_array( // + constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "BadSigature", "RublonCoreException", "BrokenData", @@ -107,7 +104,7 @@ class CoreHandlerError { class MethodError { public: enum ErrorClass { BadMethod, BadUserInput, NoMethodAvailable }; - constexpr static auto errorClassPrettyName = make_array("BadMethod", "BadUserInput", "NoMethodAvailable"); + constexpr static auto errorClassPrettyName = make_array< std::string_view >("BadMethod", "BadUserInput", "NoMethodAvailable"); constexpr static auto prettyName = "Method Error"; constexpr MethodError(ErrorClass e = BadMethod) : errorClass{e} {} @@ -127,7 +124,7 @@ class WerificationError { PasscodeException, // code: 18 TooManyRequestsException // code: 101 }; - constexpr static auto errorClassPrettyName = make_array( // + constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "BadInput", "SecurityKeyException", "PasscodeException", @@ -162,7 +159,7 @@ class RublonAuthenticationInterrupt { UserWaiting, UserNotFound }; - constexpr static auto errorClassPrettyName = make_array( // + constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "UserBypassedException", "UserDenied", "UserPending", @@ -197,7 +194,7 @@ class RublonCheckApplicationException { UnsupportedVersionException }; - constexpr static auto errorClassPrettyName = make_array( // + constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "MissingFieldException", "ApplicationNotFoundException", "InvalidSignatureException", diff --git a/PAM/ssh/include/rublon/init.hpp b/PAM/ssh/include/rublon/init.hpp index 53e6b67..df8026b 100644 --- a/PAM/ssh/include/rublon/init.hpp +++ b/PAM/ssh/include/rublon/init.hpp @@ -1,6 +1,7 @@ #pragma once #include "rublon/memory.hpp" +#include "rublon/utils.hpp" #include #include @@ -23,16 +24,19 @@ class Init : public AuthenticationStep { const char * apiPath = "/api/transaction/init"; tl::expected< MethodSelect_t, Error > createMethod(const Document & coreResponse) const { - memory::MonotonicStackResource< 256 > stackResource; + memory::MonotonicStackResource< 512 > stackResource; RapidJSONPMRAlloc alloc{&stackResource}; - const auto & rublonResponse = coreResponse["result"]; - - // const auto * rublonMethods = JSONPointer{"/result/methods", &alloc}.Get(coreResponse); + const auto * rublonMethods = JSONPointer{"/result/methods", &alloc}.Get(coreResponse); const auto * rublonTid = JSONPointer{"/result/tid", &alloc}.Get(coreResponse); - _session.updateTransactionId(rublonTid); - return MethodSelect_t{_session, rublonResponse["methods"], _session.config().prompt, _session.config().autopushPrompt}; + if(not rublonMethods) + log(LogLevel::Error, "core response has no methods"); + if(not rublonTid) + log(LogLevel::Error, "core response has no transaction ID"); + + _session.updateTransactionId(rublonTid); + return MethodSelect_t{_session, *rublonMethods, _session.config().prompt, _session.config().autopushPrompt}; } void addPamInfo(Document & coreRequest, const Pam_t & pam) const { @@ -41,39 +45,45 @@ class Init : public AuthenticationStep { } void addParams(Document & coreRequest, const Pam_t & pam) const { - memory::MonotonicStackResource< 512 > stackResource; + memory::MonotonicStackResource< 1024 > stackResource; std::pmr::string releaseInfo{&stackResource}; auto & alloc = coreRequest.GetAllocator(); const auto os = details::osName(&stackResource); + const auto host = details::hostname(&stackResource); if(os == "unknown") { log(LogLevel::Warning, "No OS information available"); } - Value osNamePretty{os.data(), static_cast< unsigned >(os.size()), alloc}; Value ip{pam.ip().get(), alloc}; Value params{rapidjson::kObjectType}; - params.AddMember("userIP", ip, alloc); params.AddMember("appVer", RUBLON_VERSION_STRING, alloc); - params.AddMember("os", osNamePretty, alloc); + if(not host.empty()) + params.AddMember("hostName", Value{os.c_str(), static_cast< unsigned >(host.size()), alloc}, alloc); + if(not _session.inInteractiveMode()) + params.AddMember("mode", "noninteractive", alloc); + params.AddMember("os", Value{os.c_str(), static_cast< unsigned >(os.size()), alloc}, alloc); + params.AddMember("userIP", Value{pam.ip().get(), alloc}, alloc); coreRequest.AddMember("params", std::move(params), alloc); } tl::expected< std::reference_wrapper< const Document >, Error > checkEnrolement(const Document & coreResponse, const Pam_t pam) const { using namespace std::string_view_literals; - const auto & resp = coreResponse; + memory::MonotonicStackResource< 256 > stackResource; + RapidJSONPMRAlloc alloc{&stackResource}; - /// TODO refactor this - if(resp.HasMember("result") and resp["result"].IsObject() and resp["result"].HasMember("status")) { - const auto & status = resp["result"]["status"].GetString(); + const auto * rublonStatus = JSONPointer{"/result/status", &alloc}.Get(coreResponse); + const auto * rublonWebURI = JSONPointer{"/result/webURI", &alloc}.Get(coreResponse); + + if(rublonStatus) { + const auto & status = rublonStatus->GetString(); log(LogLevel::Warning, "Got enrolement message with stats %s", status); if(status == "pending"sv) { - if(resp["result"].HasMember("webURI")) { - const auto & weburi = resp["result"]["webURI"].GetString(); - pam.print("Visit %s", weburi); + if(rublonWebURI) { + pam.print("Visit %s", rublonWebURI->GetString()); } } else if(status == "waiting"sv) { return tl::unexpected{Error{RublonAuthenticationInterrupt{RublonAuthenticationInterrupt::UserWaiting}}}; diff --git a/PAM/ssh/include/rublon/json.hpp b/PAM/ssh/include/rublon/json.hpp index 2a06fa1..d158600 100644 --- a/PAM/ssh/include/rublon/json.hpp +++ b/PAM/ssh/include/rublon/json.hpp @@ -1,5 +1,6 @@ #pragma once +#include "rapidjson/encodings.h" #include #include #include @@ -137,7 +138,6 @@ inline auto begin(const rublon::Value & __ils) noexcept { inline ::rublon::Value::ConstValueIterator end(const rublon::Value & __ils) noexcept { return __ils.End(); } - [[nodiscard]] inline std::size_t size(const rublon::Value & __cont) { return __cont.Size(); } diff --git a/PAM/ssh/include/rublon/method/OTP.hpp b/PAM/ssh/include/rublon/method/OTP.hpp index 365c0ed..045e5f1 100644 --- a/PAM/ssh/include/rublon/method/OTP.hpp +++ b/PAM/ssh/include/rublon/method/OTP.hpp @@ -13,7 +13,6 @@ class OTP : public PasscodeBasedAuth { public: OTP(Session & session, int prompts) : PasscodeBasedAuth(session, - "", "Mobile Passcode", "Enter the passcode from the Authenticator app: ", 6, diff --git a/PAM/ssh/include/rublon/method/PUSH.hpp b/PAM/ssh/include/rublon/method/PUSH.hpp index ba93e22..af1cad1 100644 --- a/PAM/ssh/include/rublon/method/PUSH.hpp +++ b/PAM/ssh/include/rublon/method/PUSH.hpp @@ -1,6 +1,5 @@ #pragma once -#include "rublon/session.hpp" #include #include diff --git a/PAM/ssh/include/rublon/method/SMS.hpp b/PAM/ssh/include/rublon/method/SMS.hpp index e628aab..ddf7f8d 100644 --- a/PAM/ssh/include/rublon/method/SMS.hpp +++ b/PAM/ssh/include/rublon/method/SMS.hpp @@ -12,7 +12,7 @@ namespace rublon::method { class SMS : public PasscodeBasedAuth { public: SMS(Session & session, int prompts) - : PasscodeBasedAuth(session, "", "SMS", "Enter SMS passcode: ", 6, true, PasscodeBasedAuth::Endpoint::ConfirmCode, prompts) {} + : PasscodeBasedAuth(session, "SMS", "Enter SMS passcode: ", 6, true, PasscodeBasedAuth::Endpoint::ConfirmCode, prompts) {} }; } // namespace rublon::method diff --git a/PAM/ssh/include/rublon/method/YOTP.hpp b/PAM/ssh/include/rublon/method/YOTP.hpp index 3ad8192..2140c05 100644 --- a/PAM/ssh/include/rublon/method/YOTP.hpp +++ b/PAM/ssh/include/rublon/method/YOTP.hpp @@ -11,9 +11,8 @@ namespace rublon::method { class YOTP : public PasscodeBasedAuth { public: - YOTP(Session & session, std::string accessToken, int prompts) + YOTP(Session & session, int prompts) : PasscodeBasedAuth(session, - std::move(accessToken), "YubiKey OTP Security Key", "Insert and tap your YubiKey: ", 44, diff --git a/PAM/ssh/include/rublon/method/method_select.hpp b/PAM/ssh/include/rublon/method/method_select.hpp index abe43de..616f821 100644 --- a/PAM/ssh/include/rublon/method/method_select.hpp +++ b/PAM/ssh/include/rublon/method/method_select.hpp @@ -1,11 +1,16 @@ #pragma once -#include "rublon/session.hpp" +#include +#include +#include #include #include #include +#include #include #include +#include +#include #include #include @@ -18,6 +23,9 @@ namespace rublon { +enum class MethodIds { OTP, SMS, PUSH, EMAIL, SmsLink, YOTP, PhoneCall }; +constexpr auto MethodNames = make_array< std::string_view >("totp", "sms", "push", "email", "smsLink", "yotp", "phoneCall"); + class MethodProxy { public: template < typename Method_t > @@ -43,49 +51,63 @@ class PostMethod : public AuthenticationStep { using base_t = AuthenticationStep; const char * uri = "/api/transaction/methodSSH"; - std::string _method; + MethodIds _method; int _prompts; bool _autopushPrompt; - tl::expected< MethodProxy, Error > createMethod(const Document & coreResponse) const { - /// TODO vericodeLength - const auto & rublonResponse = coreResponse["result"]; - // [[deprecated]] std::string tid = rublonResponse["tid"].GetString(); + tl::expected< void, Error > readAccessToken(const Document & coreResponse) const { + log(LogLevel::Debug, "Readding access token"); + auto alloc = RapidJSONPMRStackAlloc< 256 >{}; + const auto * rublonAccessToken = JSONPointer{"/result/token", &alloc}.Get(coreResponse); + if(rublonAccessToken) + _session.updateAccessToken(rublonAccessToken); + return {}; + } - if(_method == "totp") { - return MethodProxy{method::OTP{_session, _prompts}}; - } else if(_method == "sms") { - return MethodProxy{method::SMS{_session, _prompts}}; - } else if(_method == "push") { - return MethodProxy{method::PUSH{_session, _autopushPrompt}}; - } else if(_method == "email") { - return MethodProxy{method::EMAIL{_session}}; - } else if(_method == "smsLink") { - return MethodProxy{method::SmsLink{_session}}; - } else if(_method == "yotp") { - /// TODO assert has token - std::string token = rublonResponse.HasMember("token") ? rublonResponse["token"].GetString() : ""; - return MethodProxy{method::YOTP{_session, std::move(token), _prompts}}; - } else if(_method == "phoneCall") { - return MethodProxy{method::PhoneCall{_session}}; - } else - return tl::unexpected{MethodError{MethodError::BadMethod}}; + tl::expected< MethodProxy, Error > createMethod() const { + log(LogLevel::Debug, "Creating method"); + switch(_method) { + case rublon::MethodIds::OTP: + return MethodProxy{method::OTP{_session, _prompts}}; + + case rublon::MethodIds::SMS: + return MethodProxy{method::SMS{_session, _prompts}}; + + case rublon::MethodIds::PUSH: + return MethodProxy{method::PUSH{_session, _autopushPrompt}}; + + case rublon::MethodIds::EMAIL: + return MethodProxy{method::EMAIL{_session}}; + + case rublon::MethodIds::SmsLink: + return MethodProxy{method::SmsLink{_session}}; + + case rublon::MethodIds::YOTP: + return MethodProxy{method::YOTP{_session, _prompts}}; + + case rublon::MethodIds::PhoneCall: + return MethodProxy{method::PhoneCall{_session}}; + + default: + return tl::unexpected{MethodError{MethodError::BadMethod}}; + } } void addParams(Document & body) const { auto & alloc = body.GetAllocator(); - body.AddMember("method", Value{_method.c_str(), alloc}, alloc); + body.AddMember("method", Value{MethodNames[static_cast< int >(_method)].data(), alloc}, alloc); } public: const char * _name = "Confirm Method"; - PostMethod(Session & session, std::string method, int prompts, bool autopushPrompt) + PostMethod(Session & session, MethodIds method, int prompts, bool autopushPrompt) : base_t(session), _method{method}, _prompts{prompts}, _autopushPrompt{autopushPrompt} {} template < typename Hander_t > tl::expected< MethodProxy, Error > handle(const CoreHandlerInterface< Hander_t > & coreHandler) const { - auto createMethod = [&](const auto & coreResponse) { return this->createMethod(coreResponse); }; + auto readAccessToken = [&](const auto & coreResponse) { return this->readAccessToken(coreResponse); }; + auto createMethod = [&]() { return this->createMethod(); }; RapidJSONPMRStackAlloc< 2 * 1024 > alloc{}; Document body{rapidjson::kObjectType, &alloc}; @@ -96,6 +118,7 @@ class PostMethod : public AuthenticationStep { return coreHandler .request(alloc, uri, body) // + .and_then(readAccessToken) .and_then(createMethod); } }; @@ -110,31 +133,29 @@ class MethodSelect { public: template < typename Array_t > - MethodSelect(Session & session, const Array_t & methodsAvailableForUser, int prompts, bool autopushPrompt) + MethodSelect(Session & session, const Array_t & methodsEnabledInCore, int prompts, bool autopushPrompt) : _session{session}, _prompts{prompts}, _autopushPrompt{autopushPrompt} { + rublon::log(LogLevel::Debug, "Checking what methods from core are supported"); using namespace std::string_view_literals; - memory::MonotonicStackResource< 2024 > stackResource; - std::pmr::vector< std::string_view > _methods; - _methodsAvailable.reserve(std::size(methodsAvailableForUser)); - - std::pmr::set< std::string_view > methodsSupported{ - {"totp"sv, "email"sv, "yotp"sv, "sms"sv, "push"sv, "smsLink"sv, "phoneCall"sv}, &stackResource}; + _methodsAvailable.reserve(std::size(methodsEnabledInCore)); transform_if( - std::begin(methodsAvailableForUser), - std::end(methodsAvailableForUser), + std::begin(methodsEnabledInCore), + std::end(methodsEnabledInCore), std::back_inserter(_methodsAvailable), [&](const auto & method) { return method.GetString(); }, - [&](const auto & method) { return methodsSupported.find(method.GetString()) != methodsSupported.end(); }); + [&](const auto & method) { return std::find(MethodNames.begin(), MethodNames.end(), method.GetString()) != MethodNames.end(); }); rublon::log(LogLevel::Debug, "User has %d methods available", _methodsAvailable.size()); } tl::expected< PostMethod, Error > create(Pam_t & pam) const { rublon::log(LogLevel::Debug, "prompting user to select method"); - memory::StrictMonotonic_4k_HeapResource memoryResource; - std::pmr::map< int, std::string > methods_id{&memoryResource}; /// TODO pmr + memory::StrictMonotonic_2k_HeapResource memoryResource; + + std::pmr::map< int, MethodIds > methods_id{&memoryResource}; std::pmr::map< int, std::pmr::string > methods_names{&memoryResource}; + int prompts = _prompts; if(_methodsAvailable.size() == 0) { @@ -147,65 +168,95 @@ class MethodSelect { auto logMethodAvailable = [](auto & method) { // rublon::log(LogLevel::Debug, "Method %s found", method.c_str()); }; + auto logMethodSkippedInteractive = [](auto & method) { + rublon::log(LogLevel::Debug, "Method %s found, but skipped due non interactive mode", method.c_str()); + }; auto logMethodNotAvailable = [](auto & method) { rublon::log(LogLevel::Debug, "Method %s found, but has no handler", method.c_str()); }; auto printAvailableMethods = [&]() -> tl::expected< int, MethodError > { + rublon::log(LogLevel::Trace, "Printing available methods"); int i{}; for(const auto & method : _methodsAvailable) { if(method == "totp") { + // skipped in non interactive + if(not _session.inInteractiveMode()) { + logMethodSkippedInteractive(method); + continue; + } logMethodAvailable(method); - pam.print("%d: Passcode", i + 1); - methods_id[++i] = method; + if(_session.inInteractiveMode()) + pam.print("%d: Passcode", i + 1); + methods_id[++i] = MethodIds::OTP; methods_names[i] = "Passcode"; continue; } if(method == "email") { + // available in non interactive logMethodAvailable(method); - pam.print("%d: Email Link", i + 1); - methods_id[++i] = method; + if(_session.inInteractiveMode()) + pam.print("%d: Email Link", i + 1); + methods_id[++i] = MethodIds::EMAIL; methods_names[i] = "Email Link"; continue; } if(method == "yotp") { + // skipped in non interactive + if(not _session.inInteractiveMode()) { + logMethodSkippedInteractive(method); + continue; + } logMethodAvailable(method); - pam.print("%d: YubiKey OTP Security Key", i + 1); - methods_id[++i] = method; + if(_session.inInteractiveMode()) + pam.print("%d: YubiKey OTP Security Key", i + 1); + methods_id[++i] = MethodIds::YOTP; methods_names[i] = "YubiKey OTP Security Key"; continue; } if(method == "sms") { + // skipped in non interactive + if(not _session.inInteractiveMode()) { + logMethodSkippedInteractive(method); + continue; + } logMethodAvailable(method); - pam.print("%d: SMS Passcode", i + 1); - methods_id[++i] = method; + if(_session.inInteractiveMode()) + pam.print("%d: SMS Passcode", i + 1); + methods_id[++i] = MethodIds::SMS; methods_names[i] = "SMS Passcode"; continue; } if(method == "push") { + // available in non interactive logMethodAvailable(method); - pam.print("%d: Mobile Push", i + 1); - methods_id[++i] = method; + if(_session.inInteractiveMode()) + pam.print("%d: Mobile Push", i + 1); + methods_id[++i] = MethodIds::PUSH; methods_names[i] = "Mobile Push"; continue; } if(method == "smsLink") { + // available in non interactive logMethodAvailable(method); - pam.print("%d: SMS Link", i + 1); - methods_id[++i] = method; + if(_session.inInteractiveMode()) + pam.print("%d: SMS Link", i + 1); + methods_id[++i] = MethodIds::SmsLink; methods_names[i] = "SMS Link"; continue; } if(method == "phoneCall") { + // available in non interactive logMethodAvailable(method); - pam.print("%d: Phone Call", i + 1); - methods_id[++i] = method; + if(_session.inInteractiveMode()) + pam.print("%d: Phone Call", i + 1); + methods_id[++i] = MethodIds::PhoneCall; methods_names[i] = "Phone Call"; continue; } @@ -225,8 +276,8 @@ class MethodSelect { }; const auto createMethod = [&](std::uint32_t methodid) -> tl::expected< PostMethod, MethodError > { + rublon::log(LogLevel::Trace, "Create method %d", methods_id); auto hasMethod = methods_id.find(methodid) != methods_id.end(); - // pam.print("\t selected: %s", hasMethod ? methods_id.at(methodid).c_str() : "unknown option"); if(!hasMethod) { log(LogLevel::Error, "User selected option %d, which is not correct", methodid); return tl::unexpected{MethodError(MethodError::BadMethod)}; @@ -237,14 +288,36 @@ class MethodSelect { }; const auto askForMethod = [&](int methods_number) -> tl::expected< uint32_t, MethodError > { - if(methods_number == 1) { - pam.print("Automatically selected the only available authentication method: %s", methods_id.at(1).c_str()); - return 1; + if(not _session.inInteractiveMode()) { + log(LogLevel::Debug, "Non interactive method selection"); + /// TODO refactor, this is ugly + auto nonInteractiveMethodsPriority = + make_array< MethodIds >(MethodIds::PUSH, MethodIds::EMAIL, MethodIds::SmsLink, MethodIds::PhoneCall); + + for(const auto methodid : nonInteractiveMethodsPriority) { + for(auto [key, id] : methods_id) { + if(id == methodid) { + log(LogLevel::Debug, + "Automatically selected authentication method: %s due to working in noninteractive mode", + methods_names.at(key).c_str()); + + pam.print("Non-interctive mode enabled, choose method: %s", methods_names.at(key).c_str()); + return key; + } + } + } + return tl::unexpected{MethodError(MethodError::BadMethod)}; + } else { + if(methods_number == 1) { + pam.print("Automatically selected the only available authentication method: %s", methods_names.at(1).c_str()); + return 1; + } + return pam.scan(conv::to_uint32, "\nSelect method [1-%d]: ", methods_number).transform_error(toMethodError); } - return pam.scan(conv::to_uint32, "\nSelect method [1-%d]: ", methods_number).transform_error(toMethodError); }; auto reducePromptCount = [&](int selected_method) -> tl::expected< uint32_t, MethodError > { + rublon::log(LogLevel::Trace, "User has %d prompts available", prompts); prompts--; return selected_method; }; diff --git a/PAM/ssh/include/rublon/method/passcode_based_auth.hpp b/PAM/ssh/include/rublon/method/passcode_based_auth.hpp index 322ebec..1ba5dc9 100644 --- a/PAM/ssh/include/rublon/method/passcode_based_auth.hpp +++ b/PAM/ssh/include/rublon/method/passcode_based_auth.hpp @@ -58,6 +58,7 @@ class PasscodeBasedAuth : public AuthenticationStep { } tl::expected< std::reference_wrapper< Document >, Error > readPasscode(Document & body, const Pam_t & pam) const { + ///TODO assert in interactive mode auto & alloc = body.GetAllocator(); auto vericode = pam.scan([](const char * userInput) { return std::string{userInput}; }, userMessage); @@ -65,8 +66,8 @@ class PasscodeBasedAuth : public AuthenticationStep { Value confirmFieldValue(confirmField, alloc); body.AddMember(confirmFieldValue, Value{vericode.c_str(), alloc}, alloc); - if(token.size()) { - this->addAccessToken(body, token); + if(_session.hasAccessToken()) { + this->addAccessToken(body, _session.accessToken()); } return body; } @@ -79,18 +80,6 @@ class PasscodeBasedAuth : public AuthenticationStep { return AuthenticationStatus{AuthenticationStatus::Action::Confirmed}; } - template < typename Hander_t > - tl::expected< AuthenticationStatus, Error > waitForCoreConfirmation(const CoreHandlerInterface< Hander_t > & eventListener) const { - log(LogLevel::Info, "Listening to confirmation event in PasscodeBasedAuth"); - - auto event = eventListener.listen(); - if(event.status == transactionConfirmed ){ - log(LogLevel::Debug, " transaction confirmed jupi"); - return AuthenticationStatus{AuthenticationStatus::Action::Confirmed, std::string{event.accessToken.value().c_str()}}; - } - log(LogLevel::Debug, " transaction denied"); - return AuthenticationStatus{AuthenticationStatus::Action::Denied}; - } tl::expected< AuthenticationStatus, Error > errorHandler(Error error, const Pam_t & pam, int promptLeft) const { if(promptLeft && error.is< WerificationError >()) { @@ -114,13 +103,11 @@ class PasscodeBasedAuth : public AuthenticationStep { public: const char * _name; - std::string token; // TODO StaticString enum class Endpoint { ConfirmCode, SecurityKeySSH }; PasscodeBasedAuth( // Session & session, - std::string token, const char * _name, const char * userMessage, @@ -135,8 +122,7 @@ class PasscodeBasedAuth : public AuthenticationStep { vericodeLength{length}, onlyDigits{numbersOnly}, _prompts{prompts}, - _name{_name}, - token{std::move(token)} {} + _name{_name} {} template < typename Hander_t > tl::expected< AuthenticationStatus, Error > verify(const CoreHandlerInterface< Hander_t > & coreHandler, const Pam_t & pam) const { diff --git a/PAM/ssh/include/rublon/method/websocket_based_auth.hpp b/PAM/ssh/include/rublon/method/websocket_based_auth.hpp index 75e8c53..0625deb 100644 --- a/PAM/ssh/include/rublon/method/websocket_based_auth.hpp +++ b/PAM/ssh/include/rublon/method/websocket_based_auth.hpp @@ -6,37 +6,39 @@ #include #include #include - #include namespace rublon::method { class WebsocketBasedAuth : public AuthenticationStep { + tl::expected< void, Error > prompt(const Pam_t & pam) const { + if(not _session.inInteractiveMode()) { + return {}; + } + + if(not _autopushPrompt) + pam.print("Autopush"); + else + pam.scan([](const auto /*ignored userinput*/) { return ""; }, + "Rublon authentication initiated. Complete the authentication and press Enter to proceed"); + + return {}; + } + public: const char * _name = ""; const bool _autopushPrompt = true; WebsocketBasedAuth(Session & session, const char * name, bool autopushPrompt = true) : AuthenticationStep(session), _name{name}, _autopushPrompt{autopushPrompt} {} - - /// TODO refactor this code + template < typename Hander_t > tl::expected< AuthenticationStatus, Error > verify(const CoreHandlerInterface< Hander_t > & coreHandler, const Pam_t & pam) const { - log(LogLevel::Info, "starting WS"); - if(not _autopushPrompt) - pam.print("Autopush"); - else - pam.scan([](const auto /*ignored userinput*/) { return ""; }, - "Rublon authentication initiated. Complete the authentication and press Enter to proceed"); - - RublonEventData event = coreHandler.listen(); - - if(event.status == transactionConfirmed ){ - log(LogLevel::Debug, " transaction confirmed jupi"); - return AuthenticationStatus{AuthenticationStatus::Action::Confirmed, std::string{event.accessToken.value().c_str()}}; - } - log(LogLevel::Debug, " transaction denied"); - return AuthenticationStatus{AuthenticationStatus::Action::Denied}; + const auto promprUser = [&]() { return prompt(pam); }; + const auto waitForCoreToConfirm = [&]() { return waitForCoreConfirmation(coreHandler); }; + + return promprUser() // + .and_then(waitForCoreToConfirm); } }; diff --git a/PAM/ssh/include/rublon/pam.hpp b/PAM/ssh/include/rublon/pam.hpp index 9c9770e..5aaa0c1 100644 --- a/PAM/ssh/include/rublon/pam.hpp +++ b/PAM/ssh/include/rublon/pam.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -20,7 +21,7 @@ class LinuxPam { const void * ip = NULL; pam_get_item(pamh, PAM_RHOST, &ip); if(ip == NULL) { - rublon::log(rublon::LogLevel::Warning, "Cant read user from linux PAM"); + rublon::log(rublon::LogLevel::Warning, "Cant read ip from linux PAM"); ip = ""; } return ( const char * ) ip; @@ -40,8 +41,6 @@ class LinuxPam { void print(const char * fmt, Ti... ti) const noexcept { char buf[256] = {}; sprintf(buf, fmt, std::forward< Ti >(ti)...); - log(LogLevel::Debug, "pam_print: '%s'", buf); - if(auto r = pam_prompt(pamh, PAM_TEXT_INFO, nullptr, fmt, std::forward< Ti >(ti)...); r != PAM_SUCCESS) { log(LogLevel::Error, "pam_print returned with error code %d", r); } diff --git a/PAM/ssh/include/rublon/session.hpp b/PAM/ssh/include/rublon/session.hpp index e93d54f..bf22e19 100644 --- a/PAM/ssh/include/rublon/session.hpp +++ b/PAM/ssh/include/rublon/session.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace rublon { @@ -14,20 +15,22 @@ class Session { const Configuration _config; std::pmr::string _tid; + std::pmr::string _accessToken; CoreHandler_t _coreHandler; /// TODO log /// TODO momory resource public: - Session(const Pam_t & pam, const Configuration & config) : _pam{pam}, _config{config}, _coreHandler{_config} { + Session(const Pam_t & pam, const Configuration & config) + : _pam{pam}, _config{config}, _coreHandler{_config} { log(LogLevel::Debug, __PRETTY_FUNCTION__); } Session(Session &&) noexcept = default; Session(const Session &) = delete; - Session& operator=(Session &&) noexcept = default; - Session& operator=(const Session &) = delete; + Session & operator=(Session &&) noexcept = delete; + Session & operator=(const Session &) = delete; const auto & coreHandler() const { return _coreHandler; @@ -46,13 +49,27 @@ class Session { return systemToken().data(); } - /// TODO validate tid + bool inInteractiveMode() const { + return _config.nonInteractiveMode == false; + } + void updateTransactionId(const Value * tid) { - if(tid == nullptr) { - log(LogLevel::Warning, "Transaction ID is not defined"); - } else { - _tid = tid->GetString(); - } + log(LogLevel::Debug, "Set transaction ID %s", tid->GetString()); + _tid = tid->GetString(); + } + + void updateAccessToken(const Value * accessToken) { + log(LogLevel::Debug, "AccessToken %s", accessToken->GetString()); + _accessToken = accessToken->GetString(); + } + bool hasAccessToken() const { + return not _accessToken.empty(); + } + std::string_view accessToken() const { + return _accessToken; + } + const char * caccessToken() const { + return _accessToken.c_str(); } std::string_view transactionID() const { diff --git a/PAM/ssh/include/rublon/utils.hpp b/PAM/ssh/include/rublon/utils.hpp index 3721b4a..9078dd4 100755 --- a/PAM/ssh/include/rublon/utils.hpp +++ b/PAM/ssh/include/rublon/utils.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -33,7 +34,7 @@ inline bool readFile(const std::filesystem::path & path, T & destination) { return true; } -enum class LogLevel { Debug, Info, Warning, Error }; +enum class LogLevel { Trace, Debug, Info, Warning, Error }; inline StaticString< 32 > dateStr() { StaticString< 32 > date; @@ -43,45 +44,12 @@ inline StaticString< 32 > dateStr() { return date; } -constexpr const char * LogLevelNames[]{"Debug", "Info", "Warning", "Error"}; +constexpr const char * LogLevelNames[]{"Trace", "Debug", "Info", "Warning", "Error"}; LogLevel g_level = LogLevel::Debug; constexpr bool syncLogFile = true; static const char * application = ""; namespace details { - std::pmr::string osName(std::pmr::memory_resource * mr) { - memory::MonotonicStackResource< 8 * 1024 > stackResource; - - std::ifstream file(std::filesystem::path{"/etc/os-release"}); - if(not file.good()) - return {"unknown", mr}; - - std::pmr::string line{&stackResource}; - line.reserve(100); - - while(std::getline(file, line)) { - std::pmr::string _key{&stackResource}; - std::pmr::string _value{&stackResource}; - - if(!line.length()) - continue; - - if(line[0] == '#' || line[0] == ';') - continue; - - auto posEqual = line.find('='); - _key = line.substr(0, posEqual); - _value = line.substr(posEqual + 1); - - if(_key == "PRETTY_NAME") { - _value.erase(std::remove_if(_value.begin(), _value.end(), [](auto ch) { return ch == '"'; }), _value.end()); - return {_value, mr}; - } - } - - return {"unknown", mr}; - } - constexpr const char * logPath() { constexpr auto path = "/var/log/rublon-ssh.log"; return path; @@ -228,6 +196,49 @@ namespace details { } } + std::pmr::string hostname(std::pmr::memory_resource * mr) { + std::pmr::string hostname{512, '\0', mr}; + if(gethostname(hostname.data(), hostname.size()) != 0) { + log(LogLevel::Warning, "Hostname is not available"); + return ""; + } + hostname.resize(hostname.find_first_of('\0')); + return hostname; + } + + std::pmr::string osName(std::pmr::memory_resource * mr) { + memory::MonotonicStackResource< 8 * 1024 > stackResource; + + std::ifstream file(std::filesystem::path{"/etc/os-release"}); + if(not file.good()) + return {"unknown", mr}; + + std::pmr::string line{&stackResource}; + line.reserve(100); + + while(std::getline(file, line)) { + std::pmr::string _key{&stackResource}; + std::pmr::string _value{&stackResource}; + + if(!line.length()) + continue; + + if(line[0] == '#' || line[0] == ';') + continue; + + auto posEqual = line.find('='); + _key = line.substr(0, posEqual); + _value = line.substr(posEqual + 1); + + if(_key == "PRETTY_NAME") { + _value.erase(std::remove_if(_value.begin(), _value.end(), [](auto ch) { return ch == '"'; }), _value.end()); + return {_value, mr}; + } + } + + return {"unknown", mr}; + } + } // namespace details template < class InputIterator, class OutputIterator, class UnaryOperator, class Pred > @@ -250,4 +261,9 @@ struct ci_less { } }; +template < typename Out, typename... Types > +constexpr std::array< Out, sizeof...(Types) > make_array(Types... names) { + return {std::forward< Types >(names)...}; +} + } // namespace rublon diff --git a/PAM/ssh/include/rublon/websockets.hpp b/PAM/ssh/include/rublon/websockets.hpp index f20ac1f..e37c877 100644 --- a/PAM/ssh/include/rublon/websockets.hpp +++ b/PAM/ssh/include/rublon/websockets.hpp @@ -201,8 +201,10 @@ class WebSocket { if(input.substr(0, 2) == "42") { /// TODO assert _this /// TODO assert currentEvent + /// TODO refactor to separate class if(_this->currentEvent == nullptr) return -1; + log(LogLevel::Debug, "WS got %s", input.data()); size_t startPos = input.find("[\"") + 2; size_t endPos = input.find("\",", startPos); auto & event = *_this->currentEvent; @@ -222,7 +224,8 @@ class WebSocket { Document dataJson{&alloc}; dataJson.Parse(jsonString.data(), jsonString.size()); - const auto * data = JSONPointer{"/data", &alloc}.Get(dataJson); + const auto * data = JSONPointer{"/data", &alloc}.Get(dataJson); + const auto * redirectUrl = JSONPointer{"/redirectUrl", &alloc}.Get(dataJson); if(data != nullptr) { Document tokenJson{&alloc}; @@ -232,10 +235,11 @@ class WebSocket { if(token != nullptr) { event.accessToken = token->GetString(); } else { - log(LogLevel::Debug, "got broken data"); + log(LogLevel::Error, "Response does not contain token"); } - - log(LogLevel::Debug, "mark event received"); + _this->event_received = true; + } else if(redirectUrl != nullptr) { + log(LogLevel::Info, "Received deny message"); _this->event_received = true; } else { log(LogLevel::Error, "event data incorrect"); diff --git a/PAM/ssh/lib/pam.cpp b/PAM/ssh/lib/pam.cpp index 0f8d1cd..ee3b197 100644 --- a/PAM/ssh/lib/pam.cpp +++ b/PAM/ssh/lib/pam.cpp @@ -33,18 +33,23 @@ pam_sm_authenticate(pam_handle_t * pamh, [[maybe_unused]] int flags, [[maybe_unu using namespace rublon; details::initLog(); LinuxPam pam{pamh}; + + log(LogLevel::Info, "user '%s' authentication attempt", pam.username().get()); auto printAuthMessageAndExit = [&](const AuthenticationStatus status) { switch(status.action()) { case AuthenticationStatus::Action::Bypass: + log(LogLevel::Info, "user '%s' authentication BYPASSED", pam.username().get()); pam.print("RUBLON authentication BYPASSED"); return PAM_SUCCESS; case AuthenticationStatus::Action::Denied: + log(LogLevel::Info, "user '%s' authentication FAILED", pam.username().get()); pam.print("RUBLON authentication FAILED"); return PAM_MAXTRIES; case AuthenticationStatus::Action::Confirmed: + log(LogLevel::Info, "user '%s' authentication SUCCEEDED", pam.username().get()); pam.print("RUBLON authentication SUCCEEDED"); return PAM_SUCCESS; } @@ -95,8 +100,8 @@ pam_sm_authenticate(pam_handle_t * pamh, [[maybe_unused]] int flags, [[maybe_unu { CheckApplication ca; - auto ret = - ca.call(CH, {session.value().config().systemToken.data(), session.value().config().systemToken.size()}).or_else(mapError); + const auto & config = session.value().config(); + const auto ret = ca.call(CH, {config.systemToken.data(), config.systemToken.size()}).or_else(mapError); if(not ret.has_value()) { log(LogLevel::Error, "Check Application step failed, check configration"); return PAM_MAXTRIES; diff --git a/PAM/ssh/patches/rapidjson.patch b/PAM/ssh/patches/rapidjson.patch new file mode 100644 index 0000000..e43d863 --- /dev/null +++ b/PAM/ssh/patches/rapidjson.patch @@ -0,0 +1,51 @@ +diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h +index e3e20dfb..592c5678 100644 +--- a/include/rapidjson/document.h ++++ b/include/rapidjson/document.h +@@ -97,17 +97,20 @@ struct GenericMember { + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + template + class GenericMemberIterator + : public std::iterator >::Type> { +- ++ + friend class GenericValue; + template friend class GenericMemberIterator; + + typedef GenericMember PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef std::iterator BaseType; ++#pragma GCC diagnostic pop + + public: + //! Iterator type itself +@@ -1936,7 +1939,10 @@ private: + if (count) { + GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wclass-memaccess" + std::memcpy(e, values, count * sizeof(GenericValue)); ++#pragma GCC diagnostic pop + } + else + SetElementsPointer(0); +@@ -1949,7 +1955,10 @@ private: + if (count) { + Member* m = static_cast(allocator.Malloc(count * sizeof(Member))); + SetMembersPointer(m); ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wclass-memaccess" + std::memcpy(m, members, count * sizeof(Member)); ++#pragma GCC diagnostic pop + } + else + SetMembersPointer(0); +diff --git a/package.json b/package.json +index 843463d7..cc6087a5 100644 +Binary files a/package.json and b/package.json differ diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..7f16ccb --- /dev/null +++ b/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +source_dir=$1 +build_dir=$2 +tag=#3 + +cmake --build $build_dir -- -j +cmake --build $build_dir --target package -- -j + +cp $build_dir/*rpm $source_dir/_tmp/packages 2>/dev/null || cp $build_dir/*deb $source_dir/_tmp/packages 2>/dev/null + diff --git a/build_all.py b/build_all.py new file mode 100644 index 0000000..dd1d09d --- /dev/null +++ b/build_all.py @@ -0,0 +1,136 @@ +import os +import subprocess +from concurrent.futures import ThreadPoolExecutor, as_completed +from pydoc import doc + +# Configuration +ROOT_DIR = "./os" +MAX_WORKERS = 8 # Maximum parallel jobs for build docker image and configure project +MAX_WORKERS_COMPILE = 2 # number of compilation jobs t run + +def find_dockerfiles(root_dir): + """Recursively find all Dockerfiles in the given directory.""" + dockerfiles = [] + for dirpath, _, filenames in os.walk(root_dir): + for filename in filenames: + if filename == "Dockerfile": + dockerfiles.append(os.path.join(dirpath, filename)) + return dockerfiles + + +def tags_from_path(dockerfile): + dir_path = os.path.dirname(dockerfile) + tag = dir_path.replace(ROOT_DIR + "/", "").replace(os.path.sep, "_") + return dir_path, tag + + +def build_docker_image(dockerfile): + """Build a Docker image for the given Dockerfile.""" + dir_path, tag = tags_from_path(dockerfile) + print(f"Starting build image step for {tag} (directory: {dir_path})...") + try: + log_file = f"_tmp/logs/{tag}/build_docker_image.log" + os.makedirs(os.path.dirname(log_file), exist_ok=True) + with open(log_file, "w") as log: + result = subprocess.run( + ["docker", "build", "-t", tag, dir_path], + stdout=log, + stderr=subprocess.STDOUT, + check=True + ) + return f"Successfully built {tag}" + except subprocess.CalledProcessError: + print(f"Failed to build {tag}. Check {log_file} for details.") + return f"Failed to build {tag}" + + +in_image_source_dir = "/home/rublon-ssh" +in_image_build_dir = "/home/build" + +def configure_rublon(dockerfile): + """Build a Docker image for the given Dockerfile.""" + dir_path, tag = tags_from_path(dockerfile) + print(f"Starting configure step for {tag} (directory: {dir_path})...") + try: + log_file = f"_tmp/logs/{tag}/configure_rublon_image.log" + build_dir = f"_tmp/builds/{tag}" + os.makedirs(os.path.dirname(log_file), exist_ok=True) + os.makedirs(os.path.dirname(build_dir), exist_ok=True) + with open(log_file, "w") as log: + result = subprocess.run( + # $tag /bin/bash /home/rublon-ssh/configure.sh $tag + ["docker", "run", + "-v", f"./:{in_image_source_dir}", + "-v", f"./{build_dir}:{in_image_build_dir}", + tag, + f"{in_image_source_dir}/configure.sh", in_image_source_dir, in_image_build_dir + ], + stdout=log, + stderr=subprocess.STDOUT, + check=True + ) + return f"Successfully built {tag}" + except subprocess.CalledProcessError: + print(f"Failed to build {tag}. Check {log_file} for details.") + return f"Failed to build {tag}" + + +def build_rublon(dockerfile): + """Build a Docker image for the given Dockerfile.""" + dir_path, tag = tags_from_path(dockerfile) + print(f"Starting build for {tag} (directory: {dir_path})...") + try: + log_file = f"_tmp/logs/{tag}/compile_rublon_image.log" + build_dir = f"_tmp/builds/{tag}" + packages_dir = "_tmp/packages/" + os.makedirs(os.path.dirname(log_file), exist_ok=True) + os.makedirs(os.path.dirname(build_dir), exist_ok=True) + os.makedirs(os.path.dirname(packages_dir), exist_ok=True) + with open(log_file, "w") as log: + result = subprocess.run( + # $tag /bin/bash /home/rublon-ssh/configure.sh $tag + ["docker", "run", + "-v", f"./:{in_image_source_dir}", + "-v", f"./{build_dir}:{in_image_build_dir}", + tag, + f"{in_image_source_dir}/build.sh", in_image_source_dir, in_image_build_dir, tag + ], + stdout=log, + stderr=subprocess.STDOUT, + check=True + ) + return f"Successfully built {tag}" + except subprocess.CalledProcessError: + print(f"Failed to build {tag}. Check {log_file} for details.") + return f"Failed to build {tag}" + + +def run_parralel(num, job, name, dockerfiles): + # Use ThreadPoolExecutor for parallel builds + with ThreadPoolExecutor(max_workers=num) as executor: + future_to_dockerfile = {executor.submit(job, df): df for df in dockerfiles} + for future in as_completed(future_to_dockerfile): + dockerfile = future_to_dockerfile[future] + try: + result = future.result() + print(result) + except Exception as e: + print(f"Job {name} failed for {dockerfile}: {e}") + + +def main(): + # Find all Dockerfiles + dockerfiles = find_dockerfiles(ROOT_DIR) + if not dockerfiles: + print("No Dockerfiles found.") + return + + run_parralel(MAX_WORKERS, build_docker_image, "Docker Image Build", dockerfiles) + run_parralel(MAX_WORKERS, configure_rublon, "Configuring project", dockerfiles) + run_parralel(MAX_WORKERS_COMPILE, build_rublon, "Building project", dockerfiles) + + + print("All Docker builds completed.") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/build_all_packages.sh b/build_all_packages.sh deleted file mode 100755 index b664148..0000000 --- a/build_all_packages.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -home_dir=$PWD -echo $home_dir -find . -type f -name Dockerfile | while read -r file_path; do - dir_path=$(dirname "$file_path") - file_name=$(echo $dir_path | cut -d'/' -f3- | sed 's|/|_|g') - docker build -t "$file_name" $dir_path - docker run -v `pwd`:/home/rublon-ssh/ $file_name /bin/bash /home/rublon-ssh/build_project.sh $file_name -done diff --git a/build_package.sh b/build_package.sh deleted file mode 100755 index 7389d19..0000000 --- a/build_package.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -cmake -B rublon_ssh-build /home/rublon-ssh/ -cmake --build rublon_ssh-build/ -cmake --build rublon_ssh-build/ --target package -- -j -if [ ! -d /home/rublon-ssh/$1_packages ]; then - mkdir /home/rublon-ssh/$1_packages -fi -cp rublon_ssh-build/*rpm /home/rublon-ssh/$1_packages 2>/dev/null || cp rublon_ssh-build/*deb /home/rublon-ssh/$1_packages 2>/dev/null - diff --git a/configure.sh b/configure.sh new file mode 100755 index 0000000..e8ee21b --- /dev/null +++ b/configure.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +source_dir=$1 +build_dir=$2 + +rm -Rf $build_dir || true +cmake -B $build_dir -DCMAKE_BUILD_TYPE=Release $source_dir diff --git a/helpers/centos-base.repo b/helpers/centos-base.repo new file mode 100644 index 0000000..e779276 --- /dev/null +++ b/helpers/centos-base.repo @@ -0,0 +1,31 @@ +##################################################################### +# CentOS-Base.repo +# +# The mirror system uses the connecting IP address of the client and the +# update status of each mirror to pick mirrors that are updated to and +# geographically close to the client. You should use this for CentOS updates +# unless you are manually picking other mirrors. +# +# If the mirrorlist= does not work for you, as a fall back you can try the +# remarked out baseurl= line instead. +# +# +[centosApp] +name=CentOSApp-9 +baseurl=https://yum.oracle.com/repo/OracleLinux/OL8/appstream/x86_64/ +enabled=1 +gpgcheck=0 +gpgkey=http://mirror.centos.org/centos/8/os/x86_64/RPM-GPG-KEY-CentOS-8 +[centosApp2] +name=CentOSApp-8 +baseurl=https://yum.oracle.com/repo/OracleLinux/OL8/baseos/latest/x86_64/ +enabled=1 +gpgcheck=0 +gpgkey=http://mirror.centos.org/centos/8/os/x86_64/RPM-GPG-KEY-CentOS-8 +#[centosBase] +#name=CentOSBase-9 +#baseurl=https://mirror.stream.centos.org/9-stream/BaseOS/x86_64/os/ +#enabled=1 +#gpgcheck=0 +#gpgkey=http://mirror.centos.org/centos/8/os/x86_64/RPM-GPG-KEY-CentOS-8 +##################################################################### diff --git a/helpers/centos-base_9.repo b/helpers/centos-base_9.repo new file mode 100644 index 0000000..78d8ad1 --- /dev/null +++ b/helpers/centos-base_9.repo @@ -0,0 +1,31 @@ +##################################################################### +# CentOS-Base.repo +# +# The mirror system uses the connecting IP address of the client and the +# update status of each mirror to pick mirrors that are updated to and +# geographically close to the client. You should use this for CentOS updates +# unless you are manually picking other mirrors. +# +# If the mirrorlist= does not work for you, as a fall back you can try the +# remarked out baseurl= line instead. +# +# +[centosApp] +name=CentOSApp-9 +baseurl=https://mirror.stream.centos.org/9-stream/AppStream/x86_64/os/ +enabled=1 +gpgcheck=0 +gpgkey=http://mirror.centos.org/centos/8/os/x86_64/RPM-GPG-KEY-CentOS-8 +[centosApp2] +name=CentOSAppBase-9 +baseurl=https://mirror.stream.centos.org/9-stream/BaseOS/x86_64/os/ +enabled=1 +gpgcheck=0 +gpgkey=http://mirror.centos.org/centos/8/os/x86_64/RPM-GPG-KEY-CentOS-8 +#[centosBase] +#name=CentOSBase-9 +#baseurl=https://mirror.stream.centos.org/9-stream/BaseOS/x86_64/os/ +#enabled=1 +#gpgcheck=0 +#gpgkey=http://mirror.centos.org/centos/8/os/x86_64/RPM-GPG-KEY-CentOS-8 +##################################################################### diff --git a/os/alma/8/Vagrantfile b/os/alma/8/Vagrantfile index e1681b2..f9238c4 100644 --- a/os/alma/8/Vagrantfile +++ b/os/alma/8/Vagrantfile @@ -23,44 +23,36 @@ Vagrant.configure("2") do |config| config.vm.synced_folder "../../..", "/home/vagrant/Rublon-Linux" config.vm.provider "virtualbox" do |vb| - vb.memory = 8024 - - # Display the VirtualBox GUI when booting the machine - vb.gui = false - - # Fix for 'SSH auth method: Private key' stuck - vb.customize ["modifyvm", :id, "--cableconnected1", "on"] + vb.gui = false + vb.memory = 2048 + vb.cpus = 2 + + # Fix for 'SSH auth method: Private key' stuck + vb.customize ["modifyvm", :id, "--cableconnected1", "on"] end # Enable provisioning with a shell script. Additional provisioners such as # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=alma08 - export BUILDDIR=${BASE}/${DISTRO} + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=alma08 + export BUILDDIR=/home/vagrant/build + yum update - yum install -y --nogpgcheck gcc wget openssl-devel openssh-server libcurl-devel pam-devel git cmake policycoreutils-devel checkpolicy gcc-c++ rpm-build libubsan libasan redhat-lsb-core - - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - mkdir socket.io-client-cpp/build_alma; cd socket.io-client-cpp/build_alma - cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release .. - cmake --build . --target install - - #handle semodule - wget https://repo.almalinux.org/almalinux/8/devel/x86_64/os/Packages/rapidjson-devel-1.1.0-3.module_el8.8.0%2B3567%2B56a616e4.noarch.rpm - rpm -i rapidjson* - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build/ -- -j - cmake --build rublon_ssh-build/ --target package -- -j + yum install -y --nogpgcheck gcc gcc-c++ openssl-devel openssh-server libcurl-devel pam-devel cmake policycoreutils-devel checkpolicy rpm-build redhat-lsb-core + + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) + useradd -s /bin/bash -m bwi echo "bwi:bwi"|chpasswd - cd ./rublon_ssh-build - yum install -y rublon*.rpm + yum install -y ${BUILDDIR}/rublon*.rpm SHELL end diff --git a/os/alma/9/Vagrantfile b/os/alma/9/Vagrantfile index 393f2f3..a77d5dc 100644 --- a/os/alma/9/Vagrantfile +++ b/os/alma/9/Vagrantfile @@ -23,41 +23,35 @@ Vagrant.configure("2") do |config| config.vm.synced_folder "../../..", "/home/vagrant/Rublon-Linux" config.vm.provider "virtualbox" do |vb| - vb.memory = 8024 - vb.cpus = 4 - # Display the VirtualBox GUI when booting the machine - vb.gui = false - - # Fix for 'SSH auth method: Private key' stuck - vb.customize ["modifyvm", :id, "--cableconnected1", "on"] + vb.gui = false + vb.memory = 2048 + vb.cpus = 2 + + # Fix for 'SSH auth method: Private key' stuck + vb.customize ["modifyvm", :id, "--cableconnected1", "on"] end # Enable provisioning with a shell script. Additional provisioners such as # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=alma09 - export BUILDDIR=${BASE}/${DISTRO} + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=alma09 + export BUILDDIR=/home/vagrant/build + yum update - yum install -y --nogpgcheck gcc wget openssl-devel openssh-server libcurl-devel pam-devel git cmake policycoreutils-devel checkpolicy gcc-c++ rpm-build* + yum install -y --nogpgcheck gcc gcc-c++ openssl-devel openssh-server libcurl-devel pam-devel cmake policycoreutils-devel checkpolicy rpm-build* cp ${BASE}/helpers/centos-base_9.repo /etc/yum.repos.d/centos-base_9.repo - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - mkdir socket.io-client-cpp/build_alma; cd socket.io-client-cpp/build_alma - cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release .. - cmake --build . --target install + + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) - #handle semodule - wget https://repo.almalinux.org/almalinux/9/devel/x86_64/os/Packages/rapidjson-devel-1.1.0-19.el9.x86_64.rpm - rpm -i ./rapid* - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build/ -- -j - cmake --build rublon_ssh-build/ --target package -- -j - yum install -y ./rublon_ssh-build/rublon* + yum install -y ${BUILDDIR}/rublon* useradd -s /bin/bash -m bwi echo "bwi:bwi"|chpasswd SHELL diff --git a/os/centos/stream9/Dockerfile b/os/centos/stream9/Dockerfile index fb926c8..34aae3c 100644 --- a/os/centos/stream9/Dockerfile +++ b/os/centos/stream9/Dockerfile @@ -1,6 +1,7 @@ FROM carterjones/centos-stream9 -RUN yum update && yum install -y gcc \ +RUN yum -y update && yum install -y \ + gcc gcc-c++ \ openssl-devel \ libcurl-devel \ pam-devel \ @@ -8,8 +9,8 @@ RUN yum update && yum install -y gcc \ policycoreutils-devel \ checkpolicy \ rpm-build \ - openssh \ - gcc-c++ + openssh + WORKDIR /home/Rublon-Linux/ diff --git a/os/centos/stream9/Vagrantfile b/os/centos/stream9/Vagrantfile index b798a60..05894e3 100755 --- a/os/centos/stream9/Vagrantfile +++ b/os/centos/stream9/Vagrantfile @@ -35,27 +35,24 @@ Vagrant.configure("2") do |config| # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=centos09 - export BUILDDIR=${BASE}/${DISTRO} + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=centos09 + export BUILDDIR=/home/vagrant/${DISTRO} + yum update - yum install -y gcc openssl-devel libcurl-devel pam-devel git rapidjson-devel cmake policycoreutils-devel checkpolicy rpm-build openssh + yum install -y gcc gcc-c++ openssl-devel libcurl-devel pam-devel cmake policycoreutils-devel checkpolicy rpm-build openssh - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - mkdir socket.io-client-cpp/build; cd socket.io-client-cpp/build - cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release .. - cmake --build . --target install + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc)y + cmake --build ${BUILDDIR} --target package -j$(nproc) - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build -- -j - cmake --build rublon_ssh-build --target package -- -j useradd -s /bin/bash -m bwi echo "bwi:bwi"|chpasswd - sudo yum install -y ./rublon_ssh-build/rublon*.rpm + sudo yum install -y ${BUILDDIR}/rublon*.rpm SHELL end diff --git a/os/debian/11/Dockerfile b/os/debian/11/Dockerfile index 55a4143..c02ba20 100644 --- a/os/debian/11/Dockerfile +++ b/os/debian/11/Dockerfile @@ -1,14 +1,12 @@ FROM debian:11 ENV DEBIAN_FRONTEND=noniteracactive -RUN apt update && apt install -y gcc \ - g++ \ +RUN apt update && apt install -y \ build-essential \ openssh-server \ libcurl4-openssl-dev \ libpam0g-dev \ libssl-dev \ cmake \ - git \ file WORKDIR /home/Rublon-Linux/ diff --git a/os/debian/11/Vagrantfile b/os/debian/11/Vagrantfile index 8c908f1..63cbc40 100755 --- a/os/debian/11/Vagrantfile +++ b/os/debian/11/Vagrantfile @@ -22,50 +22,43 @@ Vagrant.configure("2") do |config| # argument is a set of non-required options. config.vm.synced_folder "../../..", "/home/vagrant/Rublon-Linux" - config.vm.provider "virtualbox" do |vb| - vb.memory = 4048 - vb.cpus = 4 - # Display the VirtualBox GUI when booting the machine - vb.gui = false - - # Fix for 'SSH auth method: Private key' stuck - vb.customize ["modifyvm", :id, "--cableconnected1", "on"] - end + config.vm.provider "virtualbox" do |vb| + vb.gui = false + vb.memory = 2048 + vb.cpus = 2 + + # Fix for 'SSH auth method: Private key' stuck + vb.customize ["modifyvm", :id, "--cableconnected1", "on"] + end # Enable provisioning with a shell script. Additional provisioners such as # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=debian11 - export BUILDDIR=${BASE}/${DISTRO} - DEBIAN_FRONTEND=noniteracactive\ - apt-get update && apt-get install -y \ - gcc \ - build-essential \ - openssh-server \ - libcurl4-openssl-dev \ - libpam0g-dev \ - libssl-dev \ - git \ - rapidjson-dev \ - cmake + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=debian11 + export BUILDDIR=/home/vagrant/build - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - cmake -B socket.io-build -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release socket.io-client-cpp - cmake --build socket.io-build --target install -- -j + DEBIAN_FRONTEND=noniteracactive \ + apt-get update && apt-get install -y \ + build-essential \ + openssh-server \ + libcurl4-openssl-dev \ + libpam0g-dev \ + libssl-dev \ + cmake - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build -- -j - cmake --build rublon_ssh-build --target package -- -j - # Register Rublon pam - - useradd -s /bin/bash -m bwi - echo "bwi:bwi"|chpasswd - sudo dpkg -i ./rublon_ssh-build/rublon* + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) + + # Register Rublon pam + useradd -s /bin/bash -m bwi + echo "bwi:bwi"|chpasswd + sudo dpkg -i ${BUILDDIR}/rublon*.deb SHELL end diff --git a/os/debian/12/Dockerfile b/os/debian/12/Dockerfile index a3f5da0..953a68c 100644 --- a/os/debian/12/Dockerfile +++ b/os/debian/12/Dockerfile @@ -1,14 +1,12 @@ FROM debian:12 ENV DEBIAN_FRONTEND=noniteracactive -RUN apt update && apt install -y gcc \ - g++ \ +RUN apt update && apt install -y \ build-essential \ openssh-server \ libcurl4-openssl-dev \ libpam0g-dev \ libssl-dev \ cmake \ - git \ file WORKDIR /home/Rublon-Linux/ diff --git a/os/debian/12/Vagrantfile b/os/debian/12/Vagrantfile index c348cdd..c77380c 100755 --- a/os/debian/12/Vagrantfile +++ b/os/debian/12/Vagrantfile @@ -23,10 +23,9 @@ Vagrant.configure("2") do |config| config.vm.synced_folder "../../..", "/home/vagrant/Rublon-Linux" config.vm.provider "virtualbox" do |vb| - # Display the VirtualBox GUI when booting the machine vb.gui = false - vb.memory = 8044 - vb.cpus = 4 + vb.memory = 2048 + vb.cpus = 2 # Fix for 'SSH auth method: Private key' stuck vb.customize ["modifyvm", :id, "--cableconnected1", "on"] @@ -36,36 +35,30 @@ Vagrant.configure("2") do |config| # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=debian12 - export BUILDDIR=${BASE}/${DISTRO} - DEBIAN_FRONTEND=noniteracactive\ - apt-get update && apt-get install -y \ - gcc \ - build-essential \ - openssh-server \ - libcurl4-openssl-dev \ - libpam0g-dev \ - libssl-dev \ - git \ - rapidjson-dev \ - cmake - - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - cmake -B socket.io-build -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release socket.io-client-cpp - cmake --build socket.io-build --target install -- -j + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=debian12 + export BUILDDIR=/home/vagrant/build - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build -- -j - cmake --build rublon_ssh-build --target package -- -j - # Register Rublon pam - - useradd -s /bin/bash -m bwi - echo "bwi:bwi"|chpasswd - sudo dpkg -i ${BUILDDIR}/rublon_ssh-build/rublon* + DEBIAN_FRONTEND=noniteracactive \ + apt-get update && apt-get install -y \ + build-essential \ + openssh-server \ + libcurl4-openssl-dev \ + libpam0g-dev \ + libssl-dev \ + cmake + + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) + + # Register Rublon pam + useradd -s /bin/bash -m bwi + echo "bwi:bwi"|chpasswd + sudo dpkg -i ${BUILDDIR}/rublon*.deb SHELL end diff --git a/os/opensuse/15sp3/Vagrantfile b/os/opensuse/15sp3/Vagrantfile index 1f280d2..ca3437b 100644 --- a/os/opensuse/15sp3/Vagrantfile +++ b/os/opensuse/15sp3/Vagrantfile @@ -37,35 +37,29 @@ Vagrant.configure("2") do |config| config.vm.provision "shell", inline: <<-SHELL export BASE=/home/vagrant/Rublon-Linux export DISTRO=opensuse15 - export BUILDDIR=${BASE}/${DISTRO} + export BUILDDIR=/home/vagrant/${DISTRO} zypper --non-interactive install -y \ gcc \ gcc-c++ \ openssh-server \ libcurl-devel \ libpamtest-devel \ - git \ - rapidjson-devel \ cmake \ pam-devel \ openssl-devel \ rpm-build - # get dependencies - mkdir ${BUILDDIR} -p; - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - cmake -B socket.io-build -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release socket.io-client-cpp - cmake --build socket.io-build --target install -- -j - - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build -- -j - cmake --build rublon_ssh-build --target package -- -j - # Register Rublon pam - - useradd -s /bin/bash -m bwi - echo "bwi:bwi"|chpasswd - sudo zypper --no-gpg-checks install -y ${BUILDDIR}/rublon_ssh-build/rublon* + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) + + # Register Rublon pam + useradd -s /bin/bash -m bwi + echo "bwi:bwi"|chpasswd + sudo zypper --no-gpg-checks install -y ${BUILDDIR}/rublon* SHELL end diff --git a/os/rhel/8/Dockerfile b/os/rhel/8/Dockerfile index 9602bee..14377c8 100644 --- a/os/rhel/8/Dockerfile +++ b/os/rhel/8/Dockerfile @@ -9,7 +9,6 @@ RUN yum update -y && yum install -y gcc \ openssh-server \ gcc-c++ \ wget -RUN wget https://yum.oracle.com/repo/OracleLinux/OL8/baseos/latest/x86_64/getPackage/pam-1.3.1-34.0.1.el8_10.x86_64.rpm \ - https://yum.oracle.com/repo/OracleLinux/OL8/baseos/latest/x86_64/getPackage/pam-devel-1.3.1-34.0.1.el8_10.x86_64.rpm +RUN wget https://yum.oracle.com/repo/OracleLinux/OL8/baseos/latest/x86_64/getPackage/pam-devel-1.3.1-34.0.1.el8_10.x86_64.rpm RUN rpm -Uvh pam* diff --git a/os/rhel/8/Vagrantfile b/os/rhel/8/Vagrantfile index 286d08a..35252e5 100644 --- a/os/rhel/8/Vagrantfile +++ b/os/rhel/8/Vagrantfile @@ -24,39 +24,40 @@ Vagrant.configure("2") do |config| # config.vm.synced_folder "../../../../socket.io", "/home/vagrant/socket.io" config.vm.provider "virtualbox" do |vb| - vb.memory = 8024 - # Display the VirtualBox GUI when booting the machine - vb.gui = false - - # Fix for 'SSH auth method: Private key' stuck - vb.customize ["modifyvm", :id, "--cableconnected1", "on"] + vb.gui = false + vb.memory = 2048 + vb.cpus = 2 + + # Fix for 'SSH auth method: Private key' stuck + vb.customize ["modifyvm", :id, "--cableconnected1", "on"] end # Enable provisioning with a shell script. Additional provisioners such as # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=rhel8 - export BUILDDIR=${BASE}/${DISTRO} - cp ${BASE}/helpers/centos-base.repo /etc/yum.repos.d/ - yum install -y openssl-devel libcurl systemd-pam git rapidjson-devel cmake pam-devel libcurl-devel libasan libubsan rpm-build redhat-lsb-core - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - cmake -B socket.io-build -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release socket.io-client-cpp - cmake --build socket.io-build --target install -- -j - useradd -s /bin/bash -m bwi - echo "bwi:bwi"|chpasswd - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build -- -j - cmake --build rublon_ssh-build --target package -- -j - # Register Rublon pam - yum -y install ./rublon_ssh-build/rublon-ssh*.el8.rpm + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=rhel8 + export BUILDDIR=/home/vagrant/build + + cp ${BASE}/helpers/centos-base.repo /etc/yum.repos.d/ + yum update + yum install -y openssl-devel libcurl systemd-pam cmake pam-devel libcurl-devel rpm-build redhat-lsb-core + + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) - SHELL + # Register Rublon pam + yum -y install ${BUILDDIR}/rublon-ssh*.el8.rpm + + useradd -s /bin/bash -m bwi + echo "bwi:bwi"|chpasswd + SHELL end diff --git a/os/rhel/9/Vagrantfile b/os/rhel/9/Vagrantfile index 3d80237..ce86f1f 100755 --- a/os/rhel/9/Vagrantfile +++ b/os/rhel/9/Vagrantfile @@ -23,41 +23,38 @@ Vagrant.configure("2") do |config| config.vm.synced_folder "../../..", "/home/vagrant/Rublon-Linux" config.vm.provider "virtualbox" do |vb| - vb.memory = 6024 - - # Display the VirtualBox GUI when booting the machine - vb.gui = false - - # Fix for 'SSH auth method: Private key' stuck - vb.customize ["modifyvm", :id, "--cableconnected1", "on"] + vb.gui = false + vb.memory = 2048 + vb.cpus = 2 + + # Fix for 'SSH auth method: Private key' stuck + vb.customize ["modifyvm", :id, "--cableconnected1", "on"] end # Enable provisioning with a shell script. Additional provisioners such as # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=rhel9 - export BUILDDIR=${BASE}/${DISTRO} - cp ${BASE}/helpers/centos-base_9.repo /etc/yum.repos.d/centos-base_9.repo + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=rhel9 + export BUILDDIR=/home/vagrant/build + + cp ${BASE}/helpers/centos-base_9.repo /etc/yum.repos.d/centos-base_9.repo yum update - yum install -y gcc openssl-devel openssh libcurl systemd-pam git rapidjson-devel cmake rpm-build lsb-release pam-devel libcurl-devel - useradd -s /bin/bash -m bwi - echo "bwi:bwi"|chpasswd - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - cmake -B socket.io-build -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release socket.io-client-cpp - cmake --build socket.io-build --target install -- -j + yum install -y gcc openssl-devel openssh libcurl systemd-pam cmake rpm-build lsb-release pam-devel libcurl-devel - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build -- -j - cmake --build rublon_ssh-build --target package -- -j - # Register Rublon pam - yum -y install ./rublon_ssh-build/rublon*.rpm + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) + # Register Rublon pam + useradd -s /bin/bash -m bwi + echo "bwi:bwi"|chpasswd + yum -y install ${BUILDDIR}/rublon*.rpm SHELL end diff --git a/os/rocky_linux/Vagrantfile b/os/rocky_linux/Vagrantfile index 3a400bc..9906dcc 100644 --- a/os/rocky_linux/Vagrantfile +++ b/os/rocky_linux/Vagrantfile @@ -23,37 +23,36 @@ Vagrant.configure("2") do |config| # argument is a set of non-required options. config.vm.provider "virtualbox" do |vb| - vb.memory = 8024 - # Display the VirtualBox GUI when booting the machine - vb.gui = false - # Fix for 'SSH auth method: Private key' stuck - vb.customize ["modifyvm", :id, "--cableconnected1", "on"] + vb.gui = false + vb.memory = 2048 + vb.cpus = 2 + + # Fix for 'SSH auth method: Private key' stuck + vb.customize ["modifyvm", :id, "--cableconnected1", "on"] end # Enable provisioning with a shell script. Additional provisioners such as # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=rocky9 - export BUILDDIR=${BASE}/${DISTRO} - yum install -y epel-release - yum install -y gcc openssl-devel systemd-pam git cmake gcc-c++ rapidjson-devel wget pam-devel rpm-build libcurl-devel policycoreutils-python-utils - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - cmake -B socket.io-build -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release socket.io-client-cpp - cmake --build socket.io-build --target install -- -j + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=rocky9 + export BUILDDIR=/home/vagrant/build + + yum install -y epel-release + yum install -y gcc gcc-c++ openssl-devel systemd-pam cmake pam-devel rpm-build libcurl-devel policycoreutils-python-utils - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build -- -j - cmake --build rublon_ssh-build --target package -- -j - useradd -s /bin/bash -m bwi - echo "bwi:bwi"|chpasswd - sudo yum install -y ./rublon_ssh-build/rublon*.rpm + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) + + useradd -s /bin/bash -m bwi + echo "bwi:bwi"|chpasswd + sudo yum install -y ./rublon_ssh-build/rublon*.rpm SHELL - end diff --git a/os/ubuntu/20.04/Dockerfile b/os/ubuntu/20.04/Dockerfile index 02b64e1..c99d695 100644 --- a/os/ubuntu/20.04/Dockerfile +++ b/os/ubuntu/20.04/Dockerfile @@ -1,7 +1,6 @@ FROM ubuntu:20.04 ENV DEBIAN_FRONTEND=noniteracactive -RUN apt update && apt install -y gcc \ - g++ \ +RUN apt update && apt install -y \ build-essential \ openssh-server \ libcurl4-openssl-dev \ diff --git a/os/ubuntu/20.04/Vagrantfile b/os/ubuntu/20.04/Vagrantfile index 6e80bae..7cf927a 100755 --- a/os/ubuntu/20.04/Vagrantfile +++ b/os/ubuntu/20.04/Vagrantfile @@ -23,50 +23,42 @@ Vagrant.configure("2") do |config| config.vm.synced_folder "../../..", "/home/vagrant/Rublon-Linux" config.vm.provider "virtualbox" do |vb| - vb.memory = 8060 - # Display the VirtualBox GUI when booting the machine - vb.gui = false - - # Fix for 'SSH auth method: Private key' stuck - vb.customize ["modifyvm", :id, "--cableconnected1", "on"] + vb.gui = false + vb.memory = 2048 + vb.cpus = 2 + + # Fix for 'SSH auth method: Private key' stuck + vb.customize ["modifyvm", :id, "--cableconnected1", "on"] end # Enable provisioning with a shell script. Additional provisioners such as # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=ubuntu2004 - export BUILDDIR=${BASE}/${DISTRO} - - DEBIAN_FRONTEND=noniteracactive\ - apt-get update && apt-get install -y \ - gcc \ - g++ \ - build-essential \ - openssh-server \ - libcurl4-openssl-dev \ - libpam0g-dev \ - libssl-dev \ - git \ - rapidjson-dev \ - cmake + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=ubuntu2004 + export BUILDDIR=/home/vagrant/build + + DEBIAN_FRONTEND=noniteracactive \ + apt-get update && apt-get install -y \ + build-essential \ + openssh-server \ + libcurl4-openssl-dev \ + libpam0g-dev \ + libssl-dev \ + cmake - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - cmake -B socket.io-build -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release socket.io-client-cpp - cmake --build socket.io-build --target install -- -j - ln -s /usr/bin/make /usr/bin/gmake - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build -- -j - cmake --build rublon_ssh-build --target package -- -j - # Register Rublon pam - - useradd -s /bin/bash -m bwi - echo "bwi:bwi"|chpasswd - sudo dpkg -i ${BUILDDIR}/rublon_ssh-build/rublon*.deb - SHELL + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) + + # Register Rublon pam + useradd -s /bin/bash -m bwi + echo "bwi:bwi"|chpasswd + sudo dpkg -i ${BUILDDIR}/rublon*.deb + SHELL end diff --git a/os/ubuntu/22.04/Dockerfile b/os/ubuntu/22.04/Dockerfile index 3ba8733..5f9ddd6 100644 --- a/os/ubuntu/22.04/Dockerfile +++ b/os/ubuntu/22.04/Dockerfile @@ -1,7 +1,6 @@ FROM ubuntu:22.04 ENV DEBIAN_FRONTEND=noniteracactive -RUN apt update && apt install -y gcc \ - g++ \ +RUN apt update && apt install -y \ build-essential \ openssh-server \ libcurl4-openssl-dev \ diff --git a/os/ubuntu/22.04/Vagrantfile b/os/ubuntu/22.04/Vagrantfile index 81b63e5..08cf101 100755 --- a/os/ubuntu/22.04/Vagrantfile +++ b/os/ubuntu/22.04/Vagrantfile @@ -23,43 +23,42 @@ Vagrant.configure("2") do |config| config.vm.synced_folder "../../..", "/home/vagrant/Rublon-Linux" config.vm.provider "virtualbox" do |vb| - vb.memory = 4000 - # Display the VirtualBox GUI when booting the machine - vb.gui = false - - # Fix for 'SSH auth method: Private key' stuck - vb.customize ["modifyvm", :id, "--cableconnected1", "on"] + vb.gui = false + vb.memory = 2048 + vb.cpus = 2 + + # Fix for 'SSH auth method: Private key' stuck + vb.customize ["modifyvm", :id, "--cableconnected1", "on"] end # Enable provisioning with a shell script. Additional provisioners such as # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=ubuntu2204 - export BUILDDIR=${BASE}/${DISTRO} - DEBIAN_FRONTEND=noniteracactive\ - apt-get update && apt-get install -y \ - gcc \ - build-essential \ - openssh-server \ - libcurl4-openssl-dev \ - libpam0g-dev \ - libssl-dev \ - git \ - rapidjson-dev \ - libwebsockets-dev \ - cmake + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=ubuntu2204 + export BUILDDIR=/home/vagrant/build - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build -- -j - cmake --build rublon_ssh-build --target package -- -j - # Register Rublon pam - - useradd -s /bin/bash -m bwi - echo "bwi:bwi"|chpasswd - sudo dpkg -i ${BUILDDIR}/rublon_ssh-build/rublon*.deb + DEBIAN_FRONTEND=noniteracactive \ + apt-get update && apt-get install -y \ + build-essential \ + openssh-server \ + libcurl4-openssl-dev \ + libpam0g-dev \ + libssl-dev \ + cmake + + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) + + # Register Rublon pam + useradd -s /bin/bash -m bwi + echo "bwi:bwi"|chpasswd + sudo dpkg -i ${BUILDDIR}/rublon*.deb SHELL end diff --git a/os/ubuntu/24.04/Dockerfile b/os/ubuntu/24.04/Dockerfile index e61132a..f14efce 100644 --- a/os/ubuntu/24.04/Dockerfile +++ b/os/ubuntu/24.04/Dockerfile @@ -1,7 +1,6 @@ FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noniteracactive -RUN apt update && apt install -y gcc \ - g++ \ +RUN apt update && apt install -y \ build-essential \ openssh-server \ libcurl4-openssl-dev \ diff --git a/os/ubuntu/24.04/Vagrantfile b/os/ubuntu/24.04/Vagrantfile index cf07b1d..f511c2f 100644 --- a/os/ubuntu/24.04/Vagrantfile +++ b/os/ubuntu/24.04/Vagrantfile @@ -22,48 +22,42 @@ Vagrant.configure("2") do |config| config.vm.synced_folder "../../..", "/home/vagrant/Rublon-Linux" config.vm.provider "virtualbox" do |vb| - vb.memory = 4000 - # Display the VirtualBox GUI when booting the machine - vb.gui = false - - # Fix for 'SSH auth method: Private key' stuck - vb.customize ["modifyvm", :id, "--cableconnected1", "on"] + vb.gui = false + vb.memory = 2048 + vb.cpus = 2 + + # Fix for 'SSH auth method: Private key' stuck + vb.customize ["modifyvm", :id, "--cableconnected1", "on"] end # Enable provisioning with a shell script. Additional provisioners such as # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the # documentation for more information about their specific syntax and use. config.vm.provision "shell", inline: <<-SHELL - export BASE=/home/vagrant/Rublon-Linux - export DISTRO=ubuntu2404 - export BUILDDIR=${BASE}/${DISTRO} - DEBIAN_FRONTEND=noniteracactive\ - apt-get update && apt-get install -y \ - gcc \ - build-essential \ - openssh-server \ - libcurl4-openssl-dev \ - libpam0g-dev \ - libssl-dev \ - git \ - rapidjson-dev \ - cmake + export BASE=/home/vagrant/Rublon-Linux + export DISTRO=ubuntu2404 + export BUILDDIR=/home/vagrant/build - # get dependencies - mkdir ${BUILDDIR} -p; cd ${BUILDDIR} - git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git - cmake -B socket.io-build -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release socket.io-client-cpp - cmake --build socket.io-build --target install -- -j - ln -s /usr/bin/make /usr/bin/gmake - # Build project - cd ${BUILDDIR} - cmake -B rublon_ssh-build .. - cmake --build rublon_ssh-build -- -j - cmake --build rublon_ssh-build --target package -- -j - # Register Rublon pam - - useradd -s /bin/bash -m bwi - echo "bwi:bwi"|chpasswd - sudo dpkg -i ${BUILDDIR}/rublon_ssh-build/rublon*.deb + DEBIAN_FRONTEND=noniteracactive \ + apt-get update && apt-get install -y \ + build-essential \ + openssh-server \ + libcurl4-openssl-dev \ + libpam0g-dev \ + libssl-dev \ + cmake + + # remove old build if exists + rm ${BUILDDIR} -Rf || true + + # build package + cmake -B ${BUILDDIR} ${BASE} + cmake --build ${BUILDDIR} -j$(nproc) + cmake --build ${BUILDDIR} --target package -j$(nproc) + + # Register Rublon pam + useradd -s /bin/bash -m bwi + echo "bwi:bwi"|chpasswd + sudo dpkg -i ${BUILDDIR}/rublon*.deb SHELL end diff --git a/pack.cmake b/pack.cmake index 977c398..bf8fefa 100644 --- a/pack.cmake +++ b/pack.cmake @@ -29,7 +29,12 @@ if ( ${outOS} MATCHES "ubuntu" OR ${outOS} MATCHES "debian" ) set(CPACK_DEBIAN_PAM-DEV_PACKAGE_NAME, YES) set(CPACK_DEB_COMPONENT_INSTALL YES) set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS YES) - +set(CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/service/login_rublon.mod" ) + list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/service/login_rublon.pp") + list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/service/login_rublon.te") + list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/service/pam_service.txt") + list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/service/rublon_veritas") + set(CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/service/inst_pubkey_rhel9.sh") execute_process ( COMMAND bash -c "awk -F= '/^VERSION_ID=/{print $2}' /etc/os-release |tr -d '\n' | tr -d '\"'" OUTPUT_VARIABLE VERSION_ID diff --git a/service/01-rublon-ssh_pubkey.conf.default b/service/01-rublon-ssh_pubkey.conf.default index 780de4c..ab5a371 100644 --- a/service/01-rublon-ssh_pubkey.conf.default +++ b/service/01-rublon-ssh_pubkey.conf.default @@ -1,6 +1,6 @@ UsePAM yes -ChallengeResponseAuthentication yes LoginGraceTime 15m +ChallengeResponseAuthentication yes AuthenticationMethods publickey,keyboard-interactive MaxAuthTries 3 PubkeyAuthentication yes diff --git a/service/helpers/postinst_pubkey b/service/helpers/postinst_pubkey deleted file mode 100644 index 2442758..0000000 --- a/service/helpers/postinst_pubkey +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -SSHD_CONF=/etc/ssh/sshd_config -SSHD_PAM_CONF=/etc/pam.d/sshd -RUBLON_SSH_CONFIG=/etc/ssh/sshd_config.d/01-rublon-ssh.conf - -cp -a /usr/share/rublon/01-rublon-ssh_pubkey.conf.default $RUBLON_SSH_CONFIG -chown root:root $RUBLON_SSH_CONFIG -chmod 640 $RUBLON_SSH_CONFIG - -if [ -f /etc/os-release ] -then - . /etc/os-release -fi -grep -qe 'auth requisite pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aauth requisite pam_rublon.so' $SSHD_PAM_CONF - -if [ ${OS} == "Ubuntu"] -then - grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aaccount required pam_rublon.so' $SSHD_PAM_CONF -fi - -grep -qe '@include common-auth' $SSHD_PAM_CONF || sed -i 's/@include common-auth/#@include common-auth/' $SSHD_PAM_CONF - -systemctrl restart sshd - diff --git a/service/helpers/postrm_rhel b/service/helpers/postrm_rhel index 53153ee..bca698b 100644 --- a/service/helpers/postrm_rhel +++ b/service/helpers/postrm_rhel @@ -3,6 +3,7 @@ RUBLON_CONFIG=/etc/rublon.config RUBLON_SSH_CONFIG=/etc/ssh/sshd_config.d/01-rublon-ssh.conf SSHD_PAM_CONF=/etc/pam.d/sshd +VERITAS_PATH=/usr/openv/netbackup/sec/at/bin/ if [ -f $RUBLON_CONFIG ] then diff --git a/service/helpers/pubkey_install_deb b/service/helpers/pubkey_install_deb deleted file mode 100644 index c4d59fc..0000000 --- a/service/helpers/pubkey_install_deb +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -SSHD_CONF=/etc/ssh/sshd_config -SSHD_PAM_CONF=/etc/pam.d/sshd -RUBLON_SSH_CONFIG=/etc/ssh/sshd_config.d/01-rublon-ssh.conf - -cp -a /usr/share/rublon/01-rublon-ssh_pubkey.conf.default $RUBLON_SSH_CONFIG -chown root:root $RUBLON_SSH_CONFIG -chmod 640 $RUBLON_SSH_CONFIG - -if [ -f /etc/os-release ] -then - . /etc/os-release -fi -sed -i '/auth required pam_rublon.so/d' $SSHD_PAM_CONF - -if [[ $ID == "rhel" || $ID=="alma" || $ID=="rocky" || $ID=="Centos" ]] -then -grep -qe 'auth required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aauth required pam_rublon.so' $SSHD_PAM_CONF -grep -qe '#auth substack password-auth' $SSHD_PAM_CONF || sed -i -e 's/auth substack password-auth/#auth substack password-auth/g' $SSHD_PAM_CONF - -elif [ $ID = "Debian" ] -then -grep -qe 'auth requisite pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aauth requisite pam_rublon.so' $SSHD_PAM_CONF -else - grep -qe 'auth requisite pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aauth requisite pam_rublon.so' $SSHD_PAM_CONF - grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aaccount required pam_rublon.so' $SSHD_PAM_CONF -fi - -grep -qe '#@include common-auth' $SSHD_PAM_CONF || sed -i 's/@include common-auth/#@include common-auth/' $SSHD_PAM_CONF -if [[ $ID == "rhel" || $ID=="alma" || $ID=="rocky" || $ID=="Centos" ]] -then -systemctl restart sshd -else -deb-systemd-invoke restart ssh.service -fi - diff --git a/service/inst_pubkey.sh b/service/inst_pubkey.sh new file mode 100644 index 0000000..4daa5da --- /dev/null +++ b/service/inst_pubkey.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +SSHD_CONF=/etc/ssh/sshd_config +SSHD_PAM_CONF=/etc/pam.d/sshd +RUBLON_SSH_CONFIG=/etc/ssh/sshd_config.d/01-rublon-ssh.conf + +cp -a /usr/share/rublon/01-rublon-ssh_pubkey.conf.default $RUBLON_SSH_CONFIG +chown root:root $RUBLON_SSH_CONFIG +chmod 640 $RUBLON_SSH_CONFIG + +grep -qe 'auth required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aauth required pam_rublon.so' $SSHD_PAM_CONF +grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aaccount required pam_rublon.so' $SSHD_PAM_CONF +grep -qe '#@include \+common-auth' $SSHD_PAM_CONF || sed -i 's/@include \+common-auth/#@include common-auth/' $SSHD_PAM_CONF + +deb-systemd-invoke restart ssh.service + + diff --git a/service/inst_pubkey_rhel_8.sh b/service/inst_pubkey_rhel_8.sh new file mode 100644 index 0000000..07a392b --- /dev/null +++ b/service/inst_pubkey_rhel_8.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +SSHD_CONF=/etc/ssh/sshd_config +SSHD_PAM_CONF=/etc/pam.d/sshd +RUBLON_SSH_CONFIG=/etc/ssh/01-rublon-ssh.conf + +cp -a /usr/share/rublon/01-rublon-ssh_pubkey.conf.default $RUBLON_SSH_CONFIG +chown root:root $RUBLON_SSH_CONFIG +chmod 640 $RUBLON_SSH_CONFIG + +grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aaccount required pam_rublon.so' $SSHD_PAM_CONF +grep -qe '#auth \+substack \+password-auth' $SSHD_PAM_CONF || sed -i 's/auth \+substack \+password-auth/#auth substack password-auth/' $SSHD_PAM_CONF + +systemctl restart sshd + diff --git a/service/inst_pubkey_rhel_9.sh b/service/inst_pubkey_rhel_9.sh new file mode 100644 index 0000000..3feffde --- /dev/null +++ b/service/inst_pubkey_rhel_9.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +SSHD_CONF=/etc/ssh/sshd_config +SSHD_PAM_CONF=/etc/pam.d/sshd +RUBLON_SSH_CONFIG=/etc/ssh/sshd_config.d/01-rublon-ssh.conf + +cp -a /usr/share/rublon/01-rublon-ssh_pubkey.conf.default $RUBLON_SSH_CONFIG +chown root:root $RUBLON_SSH_CONFIG +chmod 640 $RUBLON_SSH_CONFIG + +grep -qe 'auth required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aauth required pam_rublon.so' $SSHD_PAM_CONF +grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aaccount required pam_rublon.so' $SSHD_PAM_CONF +grep -qe '#auth \+substack \+password-auth' $SSHD_PAM_CONF || sed -i 's/auth \+substack \+password-auth/#auth substack password-auth/' $SSHD_PAM_CONF + +systemctl restart sshd + + diff --git a/service/postinst_pubkey b/service/postinst_pubkey deleted file mode 100644 index 1acc74b..0000000 --- a/service/postinst_pubkey +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -SSHD_CONF=/etc/ssh/sshd_config -SSHD_PAM_CONF=/etc/pam.d/sshd -RUBLON_CONFIG=/etc/rublon.config -RUBLON_SSH_CONFIG=/etc/ssh/sshd_config.d/01-rublon-ssh.conf - -if [ ! -f $RUBLON_CONFIG ] -then - cp -a /usr/share/rublon/rublon.config.defaults $RUBLON_CONFIG - chown root:root $RUBLON_CONFIG - chmod 640 $RUBLON_CONFIG -fi -cp -a /usr/share/rublon/service/01-rublon-ssh_pubkey.conf.default $RUBLON_SSH_CONFIG -chown root:root $RUBLON_SSH_CONFIG -chmod 640 $RUBLON_SSH_CONFIG - -if [ -f /etc/os-release ] -then - . /etc/os-release -fi - -#if [[ $ID == "rhel" || $ID=="alma" || $ID=="rocky" ]] -#then -# cd /usr/share/rublon/service - # checkmodule -M -m -o login_rublon.mod login_rublon.te -# semodule_package -o login_rublon.pp -m login_rublon.mod -# semodule -i login_rublon.pp -#fi - -grep -qe 'auth required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aauth required pam_rublon.so' $SSHD_PAM_CONF -grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aaccount required pam_rublon.so' $SSHD_PAM_CONF -grep -qe '@include common-auth' $SSHD_PAM_CONF || sed -i 's/@include common-auth/#@include common-auth/' $SSHD_PAM_CONF - -if [[ $ID == "rhel" || $ID=="alma" || $ID=="rocky" ]] -then - systemctl restart sshd -else - deb-systemd-invoke restart ssh.service -fi - diff --git a/service/pubkey_install_deb b/service/pubkey_install_deb deleted file mode 100644 index c4d59fc..0000000 --- a/service/pubkey_install_deb +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -SSHD_CONF=/etc/ssh/sshd_config -SSHD_PAM_CONF=/etc/pam.d/sshd -RUBLON_SSH_CONFIG=/etc/ssh/sshd_config.d/01-rublon-ssh.conf - -cp -a /usr/share/rublon/01-rublon-ssh_pubkey.conf.default $RUBLON_SSH_CONFIG -chown root:root $RUBLON_SSH_CONFIG -chmod 640 $RUBLON_SSH_CONFIG - -if [ -f /etc/os-release ] -then - . /etc/os-release -fi -sed -i '/auth required pam_rublon.so/d' $SSHD_PAM_CONF - -if [[ $ID == "rhel" || $ID=="alma" || $ID=="rocky" || $ID=="Centos" ]] -then -grep -qe 'auth required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aauth required pam_rublon.so' $SSHD_PAM_CONF -grep -qe '#auth substack password-auth' $SSHD_PAM_CONF || sed -i -e 's/auth substack password-auth/#auth substack password-auth/g' $SSHD_PAM_CONF - -elif [ $ID = "Debian" ] -then -grep -qe 'auth requisite pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aauth requisite pam_rublon.so' $SSHD_PAM_CONF -else - grep -qe 'auth requisite pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aauth requisite pam_rublon.so' $SSHD_PAM_CONF - grep -qe 'account required pam_rublon.so' $SSHD_PAM_CONF || sed -i '$aaccount required pam_rublon.so' $SSHD_PAM_CONF -fi - -grep -qe '#@include common-auth' $SSHD_PAM_CONF || sed -i 's/@include common-auth/#@include common-auth/' $SSHD_PAM_CONF -if [[ $ID == "rhel" || $ID=="alma" || $ID=="rocky" || $ID=="Centos" ]] -then -systemctl restart sshd -else -deb-systemd-invoke restart ssh.service -fi -