Allow setting the mode of log files

This also sets the appropriate flags in glog
This commit is contained in:
Andrew Dunham 2015-11-10 17:34:03 -08:00
parent aa4973a1b3
commit 4ccdcc7864
4 changed files with 62 additions and 3 deletions

View File

@ -266,6 +266,12 @@ Enable verbose informational messages.
Directory path for ERROR/WARN/INFO and results logging. Directory path for ERROR/WARN/INFO and results logging.
`--logger_mode=640`
File mode for output log files (provided as an octal string). Note that this
affects both the query result log and the status logs.
**Warning**: If run as root, log files may contain sensitive information!
`--value_max=512` `--value_max=512`
Maximum returned row value size. Maximum returned row value size.

View File

@ -18,12 +18,22 @@
namespace pt = boost::property_tree; namespace pt = boost::property_tree;
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
// This is the mode that glog uses for logfiles. Must be at the top level
// (i.e. outside of the `osquery` namespace).
DECLARE_int32(logfile_mode);
namespace osquery { namespace osquery {
FLAG(string, FLAG(string,
logger_path, logger_path,
"/var/log/osquery/", "/var/log/osquery/",
"Directory path for ERROR/WARN/INFO and results logging"); "Directory path for ERROR/WARN/INFO and results logging");
FLAG(int32,
logger_mode,
0640,
"Mode for log files (default '0640')");
/// Legacy, backward compatible "osquery_log_dir" CLI option. /// Legacy, backward compatible "osquery_log_dir" CLI option.
FLAG_ALIAS(std::string, osquery_log_dir, logger_path); FLAG_ALIAS(std::string, osquery_log_dir, logger_path);
@ -51,6 +61,16 @@ REGISTER(FilesystemLoggerPlugin, "logger", "filesystem");
Status FilesystemLoggerPlugin::setUp() { Status FilesystemLoggerPlugin::setUp() {
log_path_ = fs::path(FLAGS_logger_path); log_path_ = fs::path(FLAGS_logger_path);
// Ensure that the glog status logs use the same mode as our results log.
FLAGS_logfile_mode = FLAGS_logger_mode;
// Ensure that we create the results log here.
auto status = logString("");
if (!status.ok()) {
return status;
}
return Status(0, "OK"); return Status(0, "OK");
} }
@ -62,8 +82,7 @@ Status FilesystemLoggerPlugin::logStringToFile(const std::string& s,
const std::string& filename) { const std::string& filename) {
std::lock_guard<std::mutex> lock(filesystemLoggerPluginMutex); std::lock_guard<std::mutex> lock(filesystemLoggerPluginMutex);
try { try {
// The results log may contain sensitive information if run as root. auto status = writeTextFile((log_path_ / filename).string(), s, FLAGS_logger_mode, true);
auto status = writeTextFile((log_path_ / filename).string(), s, 0640, true);
if (!status.ok()) { if (!status.ok()) {
return status; return status;
} }

@ -1 +1 @@
Subproject commit f5a91963fab9e7b1481c58d55671390e12ce7757 Subproject commit c9d9d4e7ec1e80a43ee86316ca2fab6ef2fd332c

View File

@ -93,5 +93,39 @@ class DaemonTests(test_base.ProcessGenerator, unittest.TestCase):
acceptable_retcodes = [-1, -2, -1 * signal.SIGINT] acceptable_retcodes = [-1, -2, -1 * signal.SIGINT]
self.assertTrue(daemon.retcode in acceptable_retcodes) self.assertTrue(daemon.retcode in acceptable_retcodes)
def test_6_logger_mode(self):
logger_path = os.path.join(test_base.CONFIG_DIR, "logger-mode-tests")
os.makedirs(logger_path)
test_mode = 0754 # Strange mode that should never exist
daemon = self._run_daemon({
"disable_watchdog": True,
"disable_extensions": True,
"disable_logging": False,
},
options_only={
"logger_path": logger_path,
"logger_mode": test_mode,
"verbose": True,
})
info_path = os.path.join(logger_path, "osqueryd.INFO")
self.assertTrue(daemon.isAlive())
def info_exists():
return os.path.exists(info_path)
# Wait for the daemon to flush to GLOG.
test_base.expectTrue(info_exists)
# Both log files should exist and have the given mode.
for fname in ['osqueryd.INFO', 'osqueryd.results.log']:
pth = os.path.join(logger_path, fname)
self.assertTrue(os.path.exists(pth))
rpath = os.path.realpath(info_path)
mode = os.stat(rpath).st_mode & 0777
self.assertEqual(mode, test_mode)
daemon.kill()
if __name__ == '__main__': if __name__ == '__main__':
test_base.Tester().run() test_base.Tester().run()