// ---------------------------------------------------------------------- // File: com_daemon.cc // Author: Andreas-Joachim Peters - CERN // ---------------------------------------------------------------------- /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2021 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* ************************************************************************/ /*----------------------------------------------------------------------------*/ #include "console/ConsoleMain.hh" #include "console/commands/ICmdHelper.hh" #include "common/StringTokenizer.hh" #include "common/Config.hh" #include "common/Path.hh" #include "common/SymKeys.hh" /*----------------------------------------------------------------------------*/ #include #include #include #include #include #include #include /*----------------------------------------------------------------------------*/ #ifdef __APPLE__ #define EOS_PTRACE_TRACEME PT_TRACEME #define EOS_PTRACE_ATTACH PT_ATTACH #define EOS_PTRACE_DETACH PT_DETACH #else #define EOS_PTRACE_TRACEME PTRACE_TRACEME #define EOS_PTRACE_ATTACH PTRACE_ATTACH #define EOS_PTRACE_DETACH PTRACE_DETACH #endif //__APPLE__ /* Steer a service */ int com_daemon(char* arg) { #ifdef __APPLE__ fprintf(stderr,"error: daemon command is not support on OSX\n"); global_retc = EINVAL; return (0); #else eos::common::StringTokenizer subtokenizer(arg); eos::common::Config cfg; XrdOucString option = ""; XrdOucString name = ""; XrdOucString service = ""; XrdOucString subcmd; XrdOucString modules; std::vector mods; std::string chapter; std::string executable; std::string pidfile; std::string envfile; std::string cfile; bool ok = false; subtokenizer.GetLine(); if (wants_help(arg)) { goto com_daemon_usage; } option = subtokenizer.GetToken(); if (!option.length()) { goto com_daemon_usage; } if (option == "sss") { subcmd = subtokenizer.GetToken(); if (!subcmd.length()) { goto com_daemon_usage; } if (subcmd == "recreate") { if (geteuid()) { std::cerr << "error: you have to run this command as root!" << std::endl; global_retc = EPERM; return (0); } struct stat buf; std::cout << "info: you are going to (re-)create the instance sss key. A previous key will be moved to /etc/eos.keytab." << std::endl; if (!::stat("/etc/eos.keytab",&buf)) { std::string oldkeytab = "/etc/eos.keytab."; oldkeytab += std::to_string(time(NULL)); if (::rename("/etc/eos.keytab", oldkeytab.c_str())) { std::cerr << "error: renaming of existing old keytab file /etc/eos.keytab failed!" << std::endl; global_retc = errno; return (0); } } bool interactive = false; if (isatty(STDOUT_FILENO)) { interactive = true; } if (!interactive || ICmdHelper::ConfirmOperation()) { if (!::stat("/opt/eos/xrootd/bin/xrdsssadmin",&buf)) { system("yes | /opt/eos/xrootd/bin/xrdsssadmin -u daemon -g daemon -k eosmaster add /etc/eos.keytab"); system("yes | /opt/eos/xrootd/bin/xrdsssadmin -u eosnobody -g eosnobody -k eosnobody add /etc/eos.keytab"); } else { system("yes | xrdsssadmin -u daemon -g daemon -k eosmaster add /etc/eos.keytab"); system("yes | xrdsssadmin -u eosnobody -g eosnobody -k eosnobody add /etc/eos.keytab"); } system("mkdir -p /etc/eos/; cat /etc/eos.keytab | grep eosnobody > /etc/eos/fuse.sss.keytab; chmod 400 /etc/eos/fuse.sss.keytab"); std::cout << "info: recreated /etc/eos.keytab /etc/eos/fuse.sss.keytab" << std::endl; } else { global_retc = EINVAL; return (0); } return (0); } } if (option == "seal") { XrdOucString toseal = subtokenizer.GetToken(); XrdOucString sealed; std::string key; if (!toseal.length()) { return (0); } if (toseal.beginswith("/")) { // treat it as a file std::string contents; eos::common::StringConversion::LoadFileIntoString(toseal.c_str(),contents); toseal = contents.c_str(); } const char* pkey = subtokenizer.GetToken(); if (!pkey) { key = eos::common::StringConversion::StringFromShellCmd("cat /etc/eos.keytab | grep u:daemon | md5sum"); } else { key = pkey; } std::string shakey = eos::common::SymKey::Sha256(key); eos::common::SymKey::SymmetricStringEncrypt(toseal, sealed, (char*)shakey.c_str()); fprintf(stderr,"enc:%s\n", sealed.c_str()); return (0); } if ( (option != "run") && (option != "config" ) && (option != "stack" ) && (option != "stop" ) && (option != "kill") && (option != "module-init")) { goto com_daemon_usage; } service = subtokenizer.GetToken(); if ((!service.length()) || (( service != "mgm") && ( service != "mq") && ( service != "fst") && ( service != "qdb")) ){ goto com_daemon_usage; } name = subtokenizer.GetToken(); if (!name.length()) { name = service.c_str(); } modules = name; modules += ".modules"; executable = "eos-"; executable += service.c_str(); envfile = "/var/run/eos/"; envfile += executable.c_str() ; envfile += "."; envfile += name.c_str(); envfile += ".env"; pidfile = "/var/run/eos/xrd."; pidfile += service.c_str(); pidfile += "."; pidfile += name.c_str(); pidfile += ".pid"; cfg.Load("generic","all"); ok |= cfg.ok(); cfg.Load(service.c_str(), name.c_str(), false); ok |= cfg.ok(); // this might fail if there are no modules cfg.Load(service.c_str(), modules.c_str(), false); { // load all the modules: eos::common::StringConversion::Tokenize(cfg.Dump("modules", true), mods, "\n"); for ( size_t i=0; i [name] [subcmd] : \n"); fprintf(stdout, " := mq | mgm | fst | qdb\n"); fprintf(stdout, " config - configure a service / show configuration\n"); fprintf(stdout, " kill - kill -9 a given service\n"); fprintf(stdout, " run - run the given service daemon optionally identified by name\n"); fprintf(stdout, " sss recreate - re-create an instance sss key and the eosnobody keys (/etc/eos.keytab,/etc/eos/fuse.sss.keytab)'\n"); fprintf(stdout, " stack - print an 'eu-stack'\n"); fprintf(stdout, " stop - kill -15 a given service\n"); fprintf(stdout, " module-init - run the init procedure for a module\n"); fprintf(stdout,"\n"); fprintf(stdout, " examples: eos daemon config qdb qdb coup - try to make instance [qdb] a leader of QDB\n"); fprintf(stdout, " eos daemon config qdb qdb info - show raft-info for the [qdb] QDB instance\n"); fprintf(stdout, " eos daemon config qdb qdb remove host:port - remove a member of the qdb cluster\n"); fprintf(stdout, " eos daemon config qdb qdb add host:port - add an observer to the qdb cluster\n"); fprintf(stdout, " eos daemon config qdb qdb promote host:port - promote an observer to a full member of the qdb cluster\n"); fprintf(stdout, " eos daemon config qdb qdb new observer - create a new observer\n"); fprintf(stdout, " eos daemon config fst fst.1 - show the init,sysconfig and xrootd config for the [fst.1] FST service\n"); fprintf(stdout, " eos daemon kill mq - shoot the MQ service with signal -9\n"); fprintf(stdout, " eos daemon stop mq - gracefully shut down the MQ service with signal -15\n"); fprintf(stdout, " eos daemon stack mgm - take an 'eu-stack' of the MGM service\n"); fprintf(stdout, " eos daemon run fst fst.1 - run the fst.1 subservice FST\n"); global_retc = EINVAL; return (0); #endif }